多线程互斥问题
采用pthread_create建立一個新線程,與fork方式建立新進程不同(盡管在Linux環境下進程與線程具有相同概念)。所有pthread將會共用主線程中的所有變量,而不是如fork方式僅僅將所有變量引用加1。由于pthread共用問題的存在,將會引發在Linux下多線程編程的互斥問題。測試如下:
代碼示例:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <pthread.h> 4 5 int counter = 0; 6 //pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER; 7 8 void *doit(void *arg); 9 10 int main(void) 11 { 12 pthread_t tida, tidb; 13 14 pthread_create(&tida, NULL, &doit, NULL); 15 pthread_create(&tidb, NULL, &doit, NULL); 16 17 pthread_join(tida, NULL); 18 pthread_join(tidb, NULL); 19 20 exit(0); 21 } 22 23 void *doit(void *arg) 24 { 25 int i, val; 26 27 for(i = 0;i < 100; i++) { 28 //pthread_mutex_lock(&counter_mutex); 29 30 val = counter; 31 printf("%d : %d\n", pthread_self(), val + 1); 32 counter = val + 1; 33 34 //pthread_mutex_unlock(&counter_mutex); 35 } 36 37 return NULL; 38 }a與b線程執行doit函數,并將循環100次將共用變量counter加1。
輸入結果如下:
截圖1
?
截圖2:
?
截圖3:
兩個線程號分別以20,24進行標識,我們把C編譯器進行加運算符轉換為3條機器指令,第一條是從內存中取數據裝載到寄存器,第二條是遞減寄存器,第三條是從寄存器取數據存儲到內存。從截圖可以看出執行結果為:
截圖1中,20號線程首先運行,執行打印代碼并執行counter = val + 1,當其運行到counter = 10(counter=9+1)時,被CPU剝奪執行權限,此時交由24號線程運行(20號線程等待運行printf代碼),24號線程首次執行val = counter,i=0,并將當前val值賦值為10,CPU剝奪其執行權限,20號線程重新運行(24號線程等待運行printf代碼),20號線程繼續執行printf,打印輸出結果一直到打印到19,CPU剝奪執行權限交由24號線程,24號線程執行printf,打印輸出結果11(val+1)
截圖2中,24號線程一直運行,直到結束都沒有被CPU切出,但其初始值val從10開始,故最后一次打印結果為110,24號線程執行結束,返回。20號線程被CPU喚醒,執行printf,打印輸出20
截圖3中,20號線程一直運行,直到結束,返回。
?
從執行結果也可以看出,由于未加互斥操作,使得24號線程初始運行時,counter為10,而且在24號線程結束運行counter被置為109時,位于20號線程中counter沒有及時被同步,使得20號線程繼續從19開始遞增。
?
為避免上述問題存在,添加互斥鎖方式可以進行解決,將上述代碼注釋位置去掉。通過添加互斥鎖的方式,線程在操作counter變量前鎖住該互斥鎖,如果試圖對一個已經上鎖的互斥鎖上鎖,則該線程將會被阻塞,知道互斥鎖被解鎖。最終輸出結果,計數器將會單調遞增,最終值為200。
轉載于:https://www.cnblogs.com/scu-cjx/p/7736876.html
總結
- 上一篇: 2.15 更改所有者和所属组chown
- 下一篇: xss攻击入门