無鎖併發資料結構練習題 (Practice - Lock-Free Data Structures)


Question 1 - 非阻塞三層級 [recall]

「obstruction-free、lock-free、wait-free」三者的定義與進展保證各是什麼?自旋鎖屬於哪一類?


Question 2 - CAS 迴圈的細節 [recall]

無鎖堆疊的 push 中 while(!head.compare_exchange_weak(new_node->next, new_node));——CAS 失敗後為何不必重新 load head?為何用 weak 而不用 strong?


Question 3 - hazard pointer 協定 [recall]

使用 hazard pointer(風險指標)時,讀者設定 hp.store(old_head) 之後為什麼還要重新載入 head 比對?刪除者的完整流程是什麼?


Question 4 - 分離引用計數的 −2 [recall]

引用計數無鎖堆疊中,pop 成功者執行 internal_count.fetch_add(external_count - 2)。為什麼是減 2?什麼條件下由誰刪除節點?


Question 5 - ABA 問題 [recall]

什麼是 ABA 問題?哪類演算法最容易發生?一般解法是什麼?


Question 6 - 無鎖佇列的節點計數 [recall]

無鎖佇列的節點為何需要「兩個外部計數器」(external_counters:2)?為什麼它和 internal_count 必須放在同一個位域結構、用單一 CAS 更新?


Question 7 - 設計 pop 的回傳方式 [application]

你要為無鎖堆疊設計 pop 介面。同事提議「傳入 T& 引用接收結果」或「直接以值回傳 T」。指出兩者的問題並給出正確做法。


Question 8 - 消除佇列的忙等待 [application]

實測發現:多生產者無鎖佇列中,一個 push 執行緒對 data 的 CAS 成功後若被排程延遲,其他 push 執行緒全部在空轉。請套用本章技巧修改演算法。


Question 9 - 三種回收策略選型 [analysis]

你的無鎖堆疊常態處於高負載(隨時有多個執行緒在 pop),且目標平台不支援雙字 CAS(DWCAS)。比較三種記憶體回收策略,該選哪個?


Question 10 - SPSC 佇列為何不能多生產者 [analysis]

代碼 7.14 的無鎖佇列在單生產者/單消費者下完全正確,兩個生產者卻會未定義行為。從先行發生關係與競爭窗口兩方面分析原因,並說明修復思路。