SO:Inkrementacje

Z Wiki Rafał (ert16) Trójniak

Spis treści

Opis

Programy uruchamiają się w dwóch wątkach. Każdy z nich inkrementuje zmienną globalną 1000 razy. W przypadku braku synchronizacji występuje problem wyścigu, i obliczenia są niepoprawne.

1.cpp

Program do synchronizacji używa semaforów

2.cpp

Program do synchronizacji używa posixowe mutexy

Kod

1.cpp

#include <iostream>
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>
#include <sys/shm.h>
#include <sys/sem.h>
using namespace std;
 
// Zmienna którą będziemy inkrementować
int sum=0;
struct sembuf lock,unlock;
int semid;
 
 
void ipc_lock(void)
{
	if(semop(semid,&lock,1)) {
		perror("semop");
		exit(-1);
	}
}
void ipc_unlock(void)
{
	if(semop(semid,&unlock,1)) {
		perror("semop");
		exit(-1);
	}
}
void ipc_init(void)
{
	/* Inicjalizacja komend */
	unlock.sem_num=0;
	unlock.sem_op = 1;
	unlock.sem_flg= 0;
	lock.sem_num=0;
	lock.sem_op = -1;
	lock.sem_flg= 0;
 
	key_t key;
	key = ftok("1.cpp", 'R');
	if ( key==-1){
		perror("ftok");
		exit(1);
	}
 
	semid = semget(key, 0, 0);
	if(semid==-1)
	{
		printf("Tworzę semafor\n");
		semid = semget(key, 1, 0660 | IPC_CREAT);
		if(semop(semid,&unlock,1)) {
				printf("errno:%u\n",errno);
				perror("semop");
				exit(0);
		}
	}
	printf("SemId : %u\n",semid);
}
 
void ipc_destroy(void )
{
	/* Usuwam semafor */
    if (semctl(semid, 0, IPC_RMID) == -1) {
        perror("semctl");
        exit(1);
    }
}
 
// Funkcja wątku , wypisuje znak wskazywany jako argument 
static void * thread_start(void *arg)
{
	for(int i=0;i<10000;i++){
		ipc_lock();
		sum+=2;
		ipc_unlock();
	}
	return NULL;
}
 
int main(int argc, char *argv[])
{
	pthread_attr_t attr;
	pthread_t * threads;
 
	ipc_init();
 
	// Ilość uruchamianych wątków
	unsigned thread_cnt = 2;
	threads = new pthread_t[thread_cnt ];
 
	// Inicjalizacja wątków
	pthread_attr_init(&attr);
	for(unsigned i=0;i<thread_cnt ;i++)
	{
		// Startujemy wątki
		pthread_create(&(threads[i]), &attr, &thread_start, NULL);
	}
	pthread_attr_destroy(&attr);
 
	// Czekamy na zakończenia wątków
	for(unsigned i=0;i<thread_cnt ;i++)
		pthread_join(threads[i], NULL);
	// Aby ładnie wyglądało na konsoli
	cout << endl;
	cout << "Sum="<<sum<<endl;
 
	ipc_destroy();
}

2.cpp

#include <iostream>
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>
using namespace std;
 
// Zmienna którą będziemy inkrementować
int sum=0;
static pthread_mutex_t mux;
 
void ipc_lock()
{
	pthread_mutex_lock(&mux);
}
void ipc_unlock()
{
	pthread_mutex_unlock(&mux);
}
void ipc_init()
{
	// Inicjalizacja mutexa
	if(pthread_mutex_init(&mux, NULL))
	{
		perror("pthread_mutex_init");
		exit(-1);
	}
}
 
// Funkcja wątku , wypisuje znak wskazywany jako argument 
static void * thread_start(void *arg)
{
	for(int i=0;i<10000;i++){
		ipc_lock();
		sum+=2;
		ipc_unlock();
	}
	return NULL;
}
 
int main(int argc, char *argv[])
{
	pthread_attr_t attr;
	pthread_t * threads;
 
	ipc_init();
 
	// Ilość uruchamianych wątków
	unsigned thread_cnt = 2;
	threads = new pthread_t[thread_cnt ];
 
	// Inicjalizacja wątków
	pthread_attr_init(&attr);
	for(unsigned i=0;i<thread_cnt ;i++)
	{
		// Startujemy wątki
		pthread_create(&(threads[i]), &attr, &thread_start, NULL);
	}
	pthread_attr_destroy(&attr);
 
	// Czekamy na zakończenia wątków
	for(unsigned i=0;i<thread_cnt ;i++)
		pthread_join(threads[i], NULL);
	// Aby ładnie wyglądało na konsoli
	cout << endl;
	cout << "Sum="<<sum<<endl;
 
}
Osobiste