thread / mutex
引き続き MIT Open CoursewareのPractical Programming in C に取り組み中。本日はLecture13のrace conditionについて。
#include <stdlib.h> #include <stdio.h> #include <pthread.h> unsigned int cnt = 0; void *count(void *arg) { int i; for ( i = 0; i < 100000; i++ ) { cnt++; } return NULL; } int main(int argc, char* argv[]) { pthread_t tids[4]; int i; for ( i = 0; i < 4; i++ ) pthread_create(&tids[i], NULL, count, NULL); for ( i = 0; i < 4; i++ ) pthread_join(tids[i], NULL); printf("%d\n", cnt); return 0; }
$ ./a.out 315920 $ ./a.out 257619
100000 x 4 = 400000 になることを期待したいが、実際には違う。
これは、cnt++ がアセンブリレベルでは
- load cnt into a register
- increment value in register
- save new register value as new cnt
という風に分解され、アトミックに実行できないためである。
対処するにはmutexを利用する。
unsigned int cnt = 0; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; void *count(void *arg) { int i; for ( i = 0; i < 100000; i++ ) { pthread_mutex_lock(&mutex); cnt++; pthread_mutex_unlock(&mutex); } return NULL; } int main(int argc, char* argv[]) { pthread_t tids[4]; int i; for ( i = 0; i < 4; i++ ) pthread_create(&tids[i], NULL, count, NULL); for ( i = 0; i < 4; i++ ) pthread_join(tids[i], NULL); printf("%d\n", cnt); pthread_mutex_destroy(&mutex); return 0; }