併發核心問題是對資源的互斥需求,互斥的實現有多種方法(硬體方法和軟體方法)專用機器指令,較少開銷但不通用。(硬體支援)
作業系統或程式語言提供某種級別的支援。(軟體方法:作業系統和程式語言的支援)
程序承當實現互斥的責任,這是軟體方法,增加了開銷並存在缺陷。(軟體方法:程序承擔責任)
其中方法1的幾種實現有:中斷禁用、專用機器指令;2的幾種方法有:訊號量、管程、訊息傳遞等;方法3的幾種實現有dekker演算法、peterson演算法、競爭條件和訊號量等。這幾種方法的詳細說明將在本篇文章總結。
硬體實現的幾種方法有:中斷禁用,專用機器指令
中斷禁用:只需要保證乙個程序不被中斷即可,通過核心提供啟用中斷和禁用中斷的原語來支援,但是代價很高,執行的效率會明顯降低,另外不適用於多處理器
專用機器指令:compare and swap指令,用乙個測試值(testval)檢查乙個記憶體單元(*word)。如果這個記憶體單元的當前值是測試值(testval),就用新的值(newval)替換該值,否則保持不變。(當word為0可以進入臨界區,出臨界區把word重置為0,如果當前有乙個程序在訪問臨界區,其他程序的testval是1,compare and swap返回的是1,如果沒有任何程序在臨界區,testval為0,compare and swap返回的是0,如果檢查到返回的值和傳入的testval不相等,說明word的值在上一次迴圈被更改),當有程序處於臨界區時,其他程序處於忙等待(自旋等待),
機器指令只解決了互斥,可能飢餓(選擇進入臨界區的程序是任意的)和死鎖(如果p1在臨界區被中斷、並且p1在臨界區正在持有乙個資源r的訪問,那麼如果p2此時被排程執行並且試圖訪問r時就會失敗,如果p2比p1的優先順序高,p1永遠不會被執行,p2永遠處於忙等待,陷入死鎖)
todo: 表5.3 一般常用的併發機制截圖
二元訊號量 binary semaphore,值只能是0或者1
struct binary_semaphore value;
queuetype queue;
}void semwaitb(binary_semaphore s)else
}void semsignalb(binary_semaphore s)else
}
計數訊號量counting semaphore(一般訊號量 general semaphore)
struct semaphore
void semwait(semaphore s)
}void semsignal(semaphore s)
}
訊號量解決互斥問題的寫法如下
const int n= /*程序數*/;
semaphore s = 1;
void p(int i)
}void main()
訊號量的實現
semwait和semsignal的實現必須是原子原語,任何時候只有乙個程序可用semwait或者semsignal操作控制乙個訊號量。
可以使用軟體方案:dekker演算法或者peterson演算法,但這有處理開銷
可以使用硬體方案:comapare&swap和中斷禁用(單處理器系統),因為semwait和semsignal的操作時間很短,因此忙等待或者中斷禁用的時間都分長短,是比較合理的。
實現方法如下(注意important語句,並注意堵塞程序時的處理,因為堵塞程序時程序無法到達最後一句,所以堵塞時就應該執行flag置為0或者允許中斷!!!)
void semwait(semaphore s)
s.flag=0; // important ! 或: 中斷允許
}void semsignal(semaphore s)
s.flag=0; // important !
}
使用訊號量設計程式是困難的,難點在於semwait和semsignal操作可能分布在整個程式中,而且很難看出訊號量在這些操作上產生的整體效果。
管程是一種結構,可以用管程來鎖定物件。
管程是由乙個或多個過程(函式、方法)、乙個初始化序列和區域性資料組成的軟體模組。(更加物件導向),管程特點如下
程序不僅能夠在管程中被堵塞,也能夠釋放這個管程,當條件滿足且管程再次可用時,需要恢復該程序並允許它在堵塞點重新進入管程。
管程使用條件變數來支援同步,cwait(c),csignal(c),如果管程中的乙個程序發訊號,但是沒有在這個條件變數c上等待的任務,那麼丟棄這個訊號
管程優於訊號量的地方在於,所有的同步機制都被限制在管程內部,因此不但易於驗證同步的正確性,而且易於檢測出錯誤????
xx 未
和socket的關係???
2 socketserver實現併發
1 tcp socketserver伺服器端 coding utf 8 import socketserver class myserver socketserver.baserequesthandler defhandle self print conn is self.request print...
JAVA併發機制的底層實現原理
對volatile變數執行寫操作時,會在寫操作後加入一條store屏障指令。對volatile變數執行讀操作時,會在讀操作前加入一條load屏障指令。優點缺點 使用場景 偏向鎖加鎖和解鎖不需要額外的消耗,和執行非同步方法之間存在納秒級的差距 執行緒間存在鎖的競爭,會帶來額外的鎖撤銷的消耗 適用於只有...
互斥與併發 2 訊號量
1.訊號量 semaphore 為了達到訊號量的預期效果,可把訊號量看做具有整數值得變數,在它之上定義三個操作 1 乙個訊號量可以初始化為乙個非負數 2 semwait操作使訊號量減1 國內的教材將該操作稱為p 如果變成負數,那麼執行semwait的程序被阻塞,並被移入阻塞佇列。否則該程序繼續執行 ...