C - スレッド - 並列の世界 - POSIXスレッドライブラリ(pthread), スレッドセーフ, ミューテックス, ロック
Head First C ―頭とからだで覚えるCの基本、 David Griffiths(著)、 Dawn Griffiths(著)、 中田 秀基(監修)、 木下 哲也(翻訳)、 O’Reilly Media)の 12章(スレッド - 並列の世界)、p.516(長いエクササイズ)の解答を求めてみる。
Makefile
all: a.out
./a.out
a.out: main.c
cc main.c
コード
main.c
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include <stdlib.h>
void error(char *msg)
{
fprintf(stderr, "%s:%s\n", msg, strerror(errno));
exit(1);
}
int beers_a = 2000000;
pthread_mutex_t beers_lock_a = PTHREAD_MUTEX_INITIALIZER;
void *drink_lots_a(void *a)
{
pthread_mutex_lock(&beers_lock_a);
for (size_t i = 0; i < 100000; i++)
{
beers_a--;
}
pthread_mutex_unlock(&beers_lock_a);
printf("beers_a = %i\n", beers_a);
return NULL;
}
int beers_b = 2000000;
pthread_mutex_t beers_lock_b = PTHREAD_MUTEX_INITIALIZER;
void *drink_lots_b(void *a)
{
for (size_t i = 0; i < 100000; i++)
{
pthread_mutex_lock(&beers_lock_b);
beers_b--;
pthread_mutex_unlock(&beers_lock_b);
}
printf("beers_b = %i\n", beers_b);
return NULL;
}
int main()
{
// 上から順番通り
size_t count = 20;
pthread_t threads_a[count];
printf("壁にはビールが%i本\n%i本のビール\n", beers_a, beers_a);
for (size_t t = 0; t < count; t++)
{
if (pthread_create(&threads_a[t], NULL, drink_lots_a, NULL) == -1)
{
char s[255];
sprintf(s, "スレッドthreads[%zu]を作成できません。", t);
error(s);
}
}
void *result_a;
for (size_t t = 0; t < count; t++)
{
if (pthread_join(threads_a[t], &result_a) == -1)
{
char s[255];
sprintf(s, "スレッドthreads[%zu]をジョインできません。", t);
error(s);
}
}
printf("現在、壁にはビールが%i本あります。\n", beers_a);
pthread_t threads_b[count];
printf("壁にはビールが%i本\n%i本のビール\n", beers_b, beers_b);
for (size_t t = 0; t < count; t++)
{
if (pthread_create(&threads_b[t], NULL, drink_lots_b, NULL) == -1)
{
char s[255];
sprintf(s, "スレッドthreads[%zu]を作成できません。", t);
error(s);
}
}
void *result_b;
for (size_t t = 0; t < count; t++)
{
if (pthread_join(threads_b[t], &result_b) == -1)
{
char s[255];
sprintf(s, "スレッドthreads[%zu]をジョインできません。", t);
error(s);
}
}
printf("現在、壁にはビールが%i本あります。\n", beers_b);
}
入出力結果(Terminal, Zsh)
% make
cc main.c
./a.out
壁にはビールが2000000本
2000000本のビール
beers_a = 1900000
beers_a = 1800000
beers_a = 1700000
beers_a = 1600000
beers_a = 1500000
beers_a = 1400000
beers_a = 1300000
beers_a = 1200000
beers_a = 1100000
beers_a = 1000000
beers_a = 900000
beers_a = 800000
beers_a = 700000
beers_a = 600000
beers_a = 500000
beers_a = 400000
beers_a = 300000
beers_a = 200000
beers_a = 100000
beers_a = 0
現在、壁にはビールが0本あります。
壁にはビールが2000000本
2000000本のビール
beers_b = 236854
beers_b = 165839
beers_b = 123423
beers_b = 109334
beers_b = 67909
beers_b = 66788
beers_b = 63692
beers_b = 54163
beers_b = 47046
beers_b = 46461
beers_b = 43156
beers_b = 38298
beers_b = 34861
beers_b = 26016
beers_b = 15507
beers_b = 14254
beers_b = 9705
beers_b = 4361
beers_b = 1437
beers_b = 0
現在、壁にはビールが0本あります。
%