多執行緒程式設計 執行緒安全的鍊錶

2021-07-15 22:13:59 字數 1524 閱讀 8443

接下來寫乙個執行緒安全的鍊錶

雙鏈表中每個節點都有乙個指標指向列表中下乙個節點,還有乙個指標指向前乙個節點。其中不變數就是節點a中指向「下乙個」節點b的指標,還有前向指標。為了從列表中刪除乙個節點,其兩邊節點的指標都需要更新。當其中一邊更新完成時,不變數就被破壞了,直到另一邊也完成更新;在兩邊都完成更新後,不變數就又穩定了。

從乙個列表中刪除乙個節點的步驟如下

1.找到要刪除的節點n

2.更新前乙個節點指向n的指標,讓這個指標指向n的下乙個節點

3.更新後乙個節點指向n的指標,讓這個指正指向n的前乙個節點

4. 刪除節點n

執行緒間潛在問題就是修改共享資料,致使不變數遭到破壞。當不做些事來確保在這個過程中不會有其他執行緒進行訪問的話,可能就有執行緒訪問到剛剛刪除一邊的節點;這樣的話,執行緒就讀取到要刪除節點的資料(因為只有一邊的連線被修改,如圖3.1(b)),所以不變數就被破壞。破壞不變數的後果是多樣,當其他執行緒按從左往右的順序來訪問列表時,它將跳過被刪除的節點。在一方面,如有第二個執行緒嘗試刪除圖中右邊的節點,那麼可能會讓資料結構產生永久性的損壞,使程式崩潰。無論結果如何,都是並行**常見錯誤:條件競爭(race condition)。

解決方案: 使用互斥量保護列表

std::list

some_list;

mutexlock lock;

void add_to_list(int new_value)

bool list_contains(int value_to_find)

清單3.1中有乙個全域性變數①,這個全域性變數被乙個全域性的互斥量保護②。add_to_list()③和list_contains()④函式中使用lock_guard,使得這兩個函式中對資料的訪問是互斥的:list_contains()不可能看到正在被add_to_list()修改的列表。

雖然某些情況下,使用全域性變數沒問題,但在大多數情況下,互斥量通常會與保護的資料放在同乙個類中,而不是定義成全域性變數。這是物件導向設計的準則:將其放在乙個類中,就可讓他們聯絡在一起,也可對類的功能進行封裝,並進行資料保護。在這種情況下,函式add_to_list和list_contains可以作為這個類的成員函式。互斥量和要保護的資料,在類中都需要定義為private成員,這會讓訪問資料的**變的清晰,並且容易看出在什麼時候對互斥量上鎖。當所有成員函式都會在呼叫時對資料上鎖,結束時對資料解鎖,那麼就保證了資料訪問時不變數不被破壞。

當然,也不是總是那麼理想,聰明的你一定注意到了 :當其中乙個成員函式返回的是保護資料的指標或引用時,會破壞對資料的保護。具有訪問能力的指標或引用可以訪問(並可能修改)被保護的資料,而不會被互斥鎖限制。互斥量保護的資料需要對介面的設計相當謹慎,要確保互斥量能鎖住任何對保護資料的訪問,並且不留後門。

lock free 實現多執行緒安全鍊錶

lock free 實現的多執行緒鍊錶通常無法避免 aba問題。aba 問題的實質就是我們剛釋放的記憶體可能會被馬上又分配出來,被其他執行緒又放入到煉表裡了,導致interlock函式判斷鍊錶節點沒有改變 實際上節點已經被刪除過一次了,鍊錶發生了改變 而導致錯誤。那麼解決方法最有3中 一種不使用 i...

多執行緒 執行緒安全

原因 當多個執行緒同時共享,同乙個全域性變數或靜態變數。做寫的操作時,可能發生資料衝突問題,也就是執行緒安全問題。但是做讀操作是不會發生資料衝突問題。解決方案 方式一 內建鎖synchronized synchronized保證執行緒原子性,當執行緒進入方法的時候,自動獲取鎖,一旦鎖被其它執行緒獲取...

多執行緒 執行緒安全

public class unsafethread t.start while thread.activecount 1 system.out.println sum 1 從主記憶體中講sum變數複製到執行緒的工作記憶體 2 在工作記憶體中修改變數 1操作 3 將sum變數從執行緒的工作記憶體寫回到...