## 简单的多线程程序

《Head First C 中文版》第 510 页给出了一个非常简单的多线程程序 beer.c：

``````#include <stdio.h>

int beers = 2000000;

void *drink_lots(void *a)
{
int i;
for (i = 0; i < 100000; i++) {
beers = beers - 1;
}
return NULL;
}

int main()
{
int t;
printf("%i bottles of beer on the wall\n%i bottles of beer\n", beers, beers);
for (t = 0; t < 20; t++) pthread_create(&threads[t], NULL, drink_lots, NULL);
void *result;
printf("There are now %i bottles of beer on the wall\n", beers);
return 0;
}
``````

``````> gcc beer.c -lpthread -o beer
> ./beer
2000000 bottles of beer on the wall
2000000 bottles of beer
There are now 353860 bottles of beer on the wall
> ./beer
2000000 bottles of beer on the wall
2000000 bottles of beer
There are now 888389 bottles of beer on the wall
> ./beer
2000000 bottles of beer on the wall
2000000 bottles of beer
There are now 684100 bottles of beer on the wall
``````

1. 线程 1 读 beers，得 37；
2. 线程 1 将 beers 减一，得 36；
3. 线程 1 将 36 写回 beers；
4. 线程 2 读 beers，得 36；
5. 线程 2 将 beers 减一，得 35；
6. 线程 2 将 35 写回 beers。

1. 线程 1 读 beers，得 37；
2. 线程 2 读 beers，得 37；
3. 线程 2 将 beers 减一，得 36；
4. 线程 2 将 36 写回 beers；
5. 线程 1 将 beers 减一，得 36；
6. 线程 1 将 36 写回 beers。

## 版本一

``````pthread_mutex_t beers_lock = PTHREAD_MUTEX_INITIALIZER;
void *drink_lots(void *a)
{
int i;
for (i = 0; i < 100000; i++) {
beers = beers - 1;
}
printf("beers = %i\n", beers);
return NULL;
}
``````

``````> gcc beer_fixed_strategy_1.c -lpthread -o beer_fixed_strategy_1
> ./beer_fixed_strategy_1
2000000 bottles of beer on the wall
2000000 bottles of beer
beers = 1900000
beers = 1800000
beers = 1700000
beers = 1600000
beers = 1500000
beers = 1400000
beers = 1300000
beers = 1200000
beers = 1100000
beers = 1000000
beers = 900000
beers = 800000
beers = 700000
beers = 600000
beers = 500000
beers = 400000
beers = 300000
beers = 200000
beers = 100000
beers = 0
There are now 0 bottles of beer on the wall
>
``````

## 版本二

``````pthread_mutex_t beers_lock = PTHREAD_MUTEX_INITIALIZER;
void *drink_lots(void *a)
{
int i;
for (i = 0; i < 100000; i++) {
beers = beers - 1;
}
printf("beers = %i\n", beers);
return NULL;
}
``````

``````> gcc beer_fixed_strategy_2.c -lpthread -o beer_fixed_strategy_2
> ./beer_fixed_strategy_2
2000000 bottles of beer on the wall
2000000 bottles of beer
beers = 1708955
beers = 1455422
beers = 1432694
beers = 1080733
beers = 822639
beers = 610817
beers = 432912
beers = 413783
beers = 388791
beers = 370305
beers = 334197
beers = 256264
beers = 216787
beers = 189881
beers = 164612
beers = 143293
beers = 54990
beers = 18085
beers = 3175
beers = 0
There are now 0 bottles of beer on the wall
>
``````

## 多次运行

``````> ./beer_fixed_strategy_2
2000000 bottles of beer on the wall
2000000 bottles of beer
beers = 1066452
beers = 951407
beers = 929222
beers = 817108
beers = 805376
beers = 748046
beers = 738577
beers = 594522
beers = 447356
beers = 332950
beers = 280823
beers = 221191
beers = 204440
beers = 177260
beers = 147865
beers = 119168
beers = 70104
beers = 67381
beers = 11243
beers = 0
There are now 0 bottles of beer on the wall
>
``````

``````> ./beer_fixed_strategy_2
2000000 bottles of beer on the wall
2000000 bottles of beer
beers = 1135299
beers = 917185
beers = 640456
beers = 617477
beers = 466726
beers = 379176
beers = 289287
beers = 288456
beers = 259522
beers = 211679
beers = 190408
beers = 181443
beers = 144808
beers = 141295
beers = 121684
beers = 110626
beers = 63618
beers = 37551
beers = 0
beers = 10179
There are now 0 bottles of beer on the wall
``````