Linux学习之系统编程篇:线程同步的引出和思想
一、線程同步的引出
程序:父子線程交替數數
#include <stdio.h> #include <unistd.h> #include <string.h> #include <pthread.h> #define MAX 10000 //定義全局變量 int num = 0; void *func_a(void *arg) {for(int i = 0; i < MAX; i++){int cur = num;cur++;num = cur;printf("Thread A ,id = %lu, num = %d\n",pthread_self(), num);usleep(10);}return NULL; } void *func_b(void *arg) {for(int i = 0; i < MAX; i++){int cur = num;cur++;num = cur;printf("Thread B ,id = %lu, num = %d\n",pthread_self(), num);usleep(10);}return NULL; } int main() {pthread_t p1, p2;//創建兩個子線程pthread_create(&p1, NULL, func_a, NULL);pthread_create(&p2, NULL, func_b, NULL);//阻塞回收資源pthread_join(p1, NULL);pthread_join(p2, NULL);return 0; }注意:
本意:AB 線程各加 10000 次,最終應該 num = 20000
但事實上 num < 20000,意味著有 BUG。
bug 由來:
得到 num 值分 2 步:
第一步,進行加運算;
第二步,加后的 num 存入內存(存入內存,num 的值才能被輸出到屏幕)
(1)某時 num= x A 占用 CPU,加了 20 次,存入 CPU 的寄存器中,還沒來得及存入內存,就失去 CPU。
(2)此時 B 占用 CUP,A num 沒存入內存,所以 num 還是 x ,加了 30 次,存入內存,num=x+30,此時 A 又占用 CPU。
(3)A 繼續執行未完成的動作,將原先 x+20 的結果,存入內存,原 num=x+30 被覆蓋,變成 x+20,A 失去 CPU。
(4)B 繼續執行,本來應該從 x+30 開始,但卻從 x+20,因此丟失 10 個數據。
這種現象成為數據混亂,產生數據混亂的原因:
(1)有多個線程操作共享數據。
(2)CPU 的調度問題。
解決數據混亂的方法:線程同步即協同步調,按照先后順序執行操作,按上例來講,就說徹底完成 2 步后,才可以失去CPU,如果沒有徹底完成,其他線程只能等待。
二、線程同步思想
(1)先給共享資源加鎖。
(2)線程 1 要訪問共享資源,首先判斷鎖是打開還是鎖著的
如果是鎖著的則線程阻塞(阻塞在這把鎖代碼上)或者直接返回。如果是開的那么先把鎖鎖上(這樣其他線程就被阻塞在外面了),線程 1 訪問共享資源。
(3)線程 1 訪問共享資源結束:將鎖解鎖。
(4)其他線程繼續搶鎖,搶到后,上鎖,訪問共享資源,訪問結束后,解鎖 ……
注意:本來多線程訪問共享資源時候,可以并行,通過加鎖機制,并行變串行,好處是數據不會混亂,但效率會變低。
總結
以上是生活随笔為你收集整理的Linux学习之系统编程篇:线程同步的引出和思想的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux学习之系统编程篇:杀死 / 取
- 下一篇: Linux学习之系统编程篇:互斥锁(pt