#include <stdio.h>#include <pthread.h>#include <unistd.h>#include <errno.h> static int counter; // shared resourcestatic pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; void incr_counter(void *p) { do { usleep(10); // Let's have a time slice between mutex locks pthread_mutex_lock(&mutex); counter++; printf("%d\n", counter); sleep(1); pthread_mutex_unlock(&mutex); } while ( 1 );} void reset_counter(void *p) { char buf[10]; int num = 0; int rc; pthread_mutex_lock(&mutex); // block mutex just to show message printf("Enter the number and press 'Enter' to initialize the counter with new value anytime.\n"); sleep(3); pthread_mutex_unlock(&mutex); // unblock blocked mutex so another thread may work do { if ( gets(buf) != buf ) return; // NO fool-protection ! Risk of overflow ! num = atoi(buf); if ( (rc = pthread_mutex_trylock(&mutex)) == EBUSY ) { printf("Mutex is already locked by another process.\nLet's lock mutex using pthread_mutex_lock().\n"); pthread_mutex_lock(&mutex); } else if ( rc == 0 ) { printf("WOW! You are on time! Congratulation!\n"); } else { printf("Error: %d\n", rc); return; } counter = num; printf("New value for counter is %d\n", counter); pthread_mutex_unlock(&mutex); } while ( 1 );} int main(int argc, char ** argv) { pthread_t thread_1; pthread_t thread_2; counter = 0; pthread_create(&thread_1, NULL, (void *)&incr_counter, NULL); pthread_create(&thread_2, NULL, (void *)&reset_counter, NULL); pthread_join(thread_2, NULL); return 0;}
Данный пример демонстрирует совместный доступ двух потоков к общей переменной. Один поток (первый поток) в автоматическом режиме постоянно увеличивает переменную counter на единицу, при этом занимая эту переменную на целую секунду. Этот первый поток дает второму доступ к переменной countтолько на 10 миллисекунд, затем снова занимает ее на секунду. Во втором потоке предлагается ввести новое значение для переменной с терминала.
Если бы мы не использовали технологию «мьютекс», то какое значение было бы в глобальной переменной, при одновременном доступе двух потоков, нам не известно. Так же во время запуска становится очевидна разница между pthread_mutex_lock() и pthread_mutex_trylock().
Компилировать код нужно с дополнительным параметром -lpthread:
$ gcc -o mutex -lpthread mutex.c
Запускаем и меняем значение переменной просто вводя новое значение в терминальном окне: $ ./mutex
Enter the number and press 'Enter' to initialize the counter with new value anytime.12330 <Enter> <--- новое значение переменнойMutex is already locked by another process.Let's lock mutex using pthread_mutex_lock().New value for counter is 303132331 <Enter> <--- новое значение переменнойMutex is already locked by another process.Let's lock mutex using pthread_mutex_lock().New value for counter is 123