4.鎖--無鎖程式設計以及CAS
阿新 • • 發佈:2019-01-26
無鎖程式設計 / lock-free / 非阻塞同步
無鎖程式設計,即不使用鎖的情況下實現多執行緒之間的變數同步,也就是在沒有執行緒被阻塞的情況下實現變數的同步,所以也叫非阻塞同步(Non-blocking Synchronization)。 lock-free是目前最常見的無鎖程式設計的實現級別(一共三種級別)。為什麼要 Non-blocking sync ?
使用lock實現執行緒同步有很多缺點: * 產生競爭時,執行緒被阻塞等待,無法做到執行緒實時響應。 * dead lock。 * live lock。 * 優先順序翻轉。 * 使用不當,造成效能下降。 如果在不使用 lock 的情況下,實現變數同步,那就會避免很多問題。雖然目前來看,無鎖程式設計並不能替代 lock。
實現級別
非同步阻塞的實現可以分成三個級別:wait-free/lock-free/obstruction-free。
wait-free
是最理想的模式,整個操作保證每個執行緒在有限步驟下完成。
保證系統級吞吐(system-wide throughput)以及無執行緒飢餓。
截止2011年,沒有多少具體的實現。即使實現了,也需要依賴於具體CPU。
lock-free
允許個別執行緒飢餓,但保證系統級吞吐。
確保至少有一個執行緒能夠繼續執行。
wait-free的演算法必定也是lock-free的。
obstruction-free
在任何時間點,一個執行緒被隔離為一個事務進行執行(其他執行緒suspended),並且在有限步驟內完成。在執行過程中,一旦發現數據被修改(採用時間戳、版本號),則回滾。
也叫做樂觀鎖,即CAS原語
LL/SC, atom read-modify-write 如果CPU提供了Load-Link/Store-Conditional(LL/SC)這對指令,則就可以輕鬆實現變數的CPU級別無鎖同步。 LL [addr],dst:從記憶體[addr]處讀取值到dst。 SC value,[addr]:對於當前執行緒,自從上次的LL動作後記憶體值沒有改變,就更新成新值。 上述過程就是實現lock-free的 read-modify-write 的原子操作。 CAS (Compare-And-Swap)Bool CAS(T* addr, T expected, T newValue) { if( *addr == expected ) { *addr = newValue; return true; } else return false; }ABA 問題 thread1意圖對val=1進行操作變成2,cas(*val,1,2)。 thread1先讀取val=1;thread1被搶佔(preempted),讓thread2執行。 thread2 修改val=3,又修改回1。 thread1繼續執行,發現期望值與“原值”(其實被修改過了)相同,完成CAS操作。 使用CAS會造成ABA問題,特別是在使用指標操作一些併發資料結構時。 解決方案 ABAʹ:新增額外的標記用來指示是否被修改。