線程並發會引發一些難以發現的錯誤,現在就來看一個簡單的線程的並發導致的問題,首先來看下面程式,程式很簡單,就是建立了3個線程,第一個線程對i和count加1,第二個線程對j和count加1,第三個線程對k和count加1,i,j,k,count初始化都為0,這樣的華,按照邏輯來說,最後i+j+k = count:
1 #include<stdio.h>
2 #include<stdlib.h>
3 #include<pthread.h>
4
5 int count = 0;
6 int i = 0;
7 int j = 0;
8 int k = 0;
9
10 /*給i的值和count的值加1*/
11 void *modify_i_thread(void *data)
12 {
13 for(;;) {
14 i++;
15 count++;
16 }
17 }
18
19 /*給j的值和count的值加1*/
20 void *modify_j_thread(void *data)
21 {
22 for(;;) {
23 j++;
24 count++;
25 }
26 }
27
28 /*給k的值和count的值加1*/
29 void *modify_k_thread(void *data)
30 {
31 for(;;) {
32 k++;
33 count++;
34 }
35 }
36
37 int main(void)
38 {
39 pthread_t pthid;
40
41 /*建立三個線程 */
42 pthread_create(&pthid, NULL, modify_i_thread, NULL);
43 pthread_create(&pthid, NULL, modify_j_thread, NULL);
44 pthread_create(&pthid, NULL, modify_k_thread, NULL);
45
46 sleep(1);
47
48 /*列印結果 */
49 printf("i = %d, j = %d, k= %d, count = %d\n", i, j, k, count);
50 printf("i+j+k=%d\n", i + j + k);
51
52 return 0;
53 }
在我機子上執行的結果是:
i = 92394160, j = 55544601, k= 42663454, count = 74003307
i+j+k=190606856
很明顯,i+j+k != count,為什麼會發生這樣的問題呢?首先我們可以肯定的是,按照數學邏輯上講,本文一開始的假定(i+j+k = count)是正確的,但是執行結果卻出乎我們的意料,或許,問題就出線上程的並發執行上。再來仔細分析下建立的線程執行的操作,3個線程中都對count進行了++操作,++操作在C語言中看起來是一條語句,實際上編譯後是3條語句,首先將count的值寫入寄存器,然後對其進行加1操作,在接著將寄存器的值讀出,儲存在count中。現在來再看看這個程式,三個線程簡稱為A、B、C,如果A剛剛把count的值寫入寄存器中,此時發送器調度B線程開始運行,這個時候,B對count進行了N次加法操作,此時count = count+N,此時發送器恢複執行A線程,那麼此時A中儲存的count的值卻是是B線程執行前的值,此時,A再對count進行操作時,就是基於舊的值(其他線程對count進行操作前的值),而不是最新的值,所以count的值並不是我們期望中的值。
一個小小的並發程式,卻也引出了這樣的一個問題,所以在遇到並發程式時,最好先想想怎麼樣利用同步和互斥操作來避免這樣的錯誤。錯誤之處,還輕您斧正。先謝謝啦。