POSIX Threads/Przykładowe programy/Program 15

Z Wikibooks, biblioteki wolnych podręczników.
Przejdź do nawigacji Przejdź do wyszukiwania
/*
 *	Przykładowy program dla kursu "POSIX Threads" z wikibooks.pl
 *
 *	Temat: 	sekcja krytyczna z użyciem mutexów
 *		jeśli zdefiniowane zostanie BLOKADA, mutex blokuje
 *		dostęp do zmiennej, w przeciwnym razie wątki zmieniają
 *		ją bez żadnej synchronizacji, co może prowadzić do błędu
 *
 *	Autor: Wojciech Muła
 *	Ostatnia zmiana: 2010-03-xx
 */
#define _POSIX_C_SOURCE	200809L
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <errno.h>

#define test_errno(msg) do{if (errno) {perror(msg); exit(EXIT_FAILURE);}} while(0)


#define	N 10	/* liczba wątków */
#define K 1000	/* liczba iteracji (z tą wartością należy eksperymentować) */

pthread_mutex_t blokada;
int licznik = 0;		// globalny licznik, powinien być chroniony blokadą

void ms_sleep(unsigned ms) {
	struct timespec req;
	req.tv_sec  = (ms / 1000);
	req.tv_nsec = (ms % 1000 * 1000000);
	nanosleep(&req, NULL);
}
//------------------------------------------------------------------------

void* watek(void* numer) {
	int i;
	for (i=0; i < K; i++) {
#ifdef BLOKADA
		errno = pthread_mutex_lock(&blokada);
		test_errno("pthread_mutex_lock");
#endif
		licznik = licznik + 1;
		ms_sleep(1);
#ifdef BLOKADA
		errno = pthread_mutex_unlock(&blokada);
		test_errno("pthread_mutex_unlock");
#endif
	}

	return NULL;
}
//------------------------------------------------------------------------

int main() {
	pthread_t id[N];
	int i;

	printf("licznik = %d\n", licznik);

	errno = pthread_mutex_init(&blokada, NULL);
	test_errno("pthread_mutex_init");

	/* utworzenie wątku */
	for (i=0; i < N; i++) {
		errno = pthread_create(&id[i], NULL, watek, (void*)i);
		test_errno("pthread_create");
	}

	/* oczekiwanie na jego zakończenie */
	for (i=0; i < N; i++) {
		errno = pthread_join(id[i], NULL);
		test_errno("pthread_join");
	}

	printf("licznik = %d, spodziewana wartość = %d %s\n",
		licznik,
		N*K,
		(licznik != N*K ? "BŁĄD!!!" : "")
	);

	return EXIT_SUCCESS;
}
//------------------------------------------------------------------------