編程語言或處理器已經具有“默認”原子操作,據我所知,我們可以使用它們。
https://en.wikipedia.org/wiki/Linearizability
uj5u.com熱心網友回復:
原子操作和臨界區有什么區別?
原子操作是保證共享(小)變數的原子訪問/更新的指令。這通常包括諸如遞增、遞減、加法、減法、比較和交換(又名 CAS)、交換、邏輯操作(與、或、異或)以及基本加載/存盤之類的操作。如果要執行目標平臺不支持的非平凡操作(或涉及大變數的操作),則不能使用原子操作。這意味著要么需要其中的多個,要么應該使用另一種機制(例如,臨界區、事務性記憶體)。請注意,使用多個原子操作通常會使事情變得更加復雜(參見ABA 問題)。在主流 CPU 上,原子操作通常是通過鎖定共享快取(例如 L3)的快取行來實作的,這樣一次只有一個執行緒可以訪問它。
臨界區旨在保護一條或多條指令不被多個執行緒同時執行。它們通常使用系統互斥鎖進行保護。進入臨界區的執行緒會鎖定相關聯的互斥體,并在離開臨界區時將其解鎖。如果關聯的互斥鎖已被鎖定,系統互斥鎖會導致進入臨界區的執行緒等待。這通常使用背景關系切換來完成(執行緒被取消調度并稍后重新調度)。
當鎖很少被另一個執行緒占用時,臨界區可能是有效的。背景關系切換會顯著影響性能。當許多執行緒對其執行原子操作時,原子操作也不是很好。爭用效應會使原子訪問顯著變慢(例如自旋鎖)。對于原子 CAS 操作尤其如此。某些平臺可以非常快速地執行原子操作(例如 GPU),因為它們具有專用單元來有效地執行原子操作。
兩者中的哪一個可以防止背景關系切換?
兩者都不能防止背景關系切換。現代作業系統可以隨時執行背景關系切換。話雖如此,臨界區通常會導致背景關系切換:試圖進入已被另一個執行緒鎖定的臨界區的執行緒通常會進入睡眠模式,并在另一個執行緒解鎖該部分時被作業系統調度程式喚醒。原子操作不會影響系統的調度(至少在主流平臺上不會)。
請注意,上述文本也適用于行程。
uj5u.com熱心網友回復:
只談命名法問題:
“原子”的意思是“不能分解成更小的部分”。在編程中,如果其他執行緒無法看到處于中途完成狀態的操作,則由一個執行緒執行的操作是“原子的”(從其他執行緒來看)。從其他執行緒的角度來看,就好像整個操作發生在一個瞬間。它要么已經發生,要么還沒有發生。兩者之間沒有。
正如 Jér?me Richard 所指出的,現代計算機硬體提供了對簡單變數的原子操作。通過在棘手的非??阻塞演算法中使用硬體原子,或者在互斥鎖的實作中使用硬體原子,我們可以使用它們使更復雜的操作從其他執行緒的角度看起來“原子”。
“關鍵部分”來自多執行緒之前的時間。在作業系統內核代碼和“裸機”應用程式代碼中,代碼主體和中斷處理程式之間始終存在有限形式的并發。“關鍵部分”在過去是指代碼主體中的一個例程,通過在禁用中斷的情況下執行它來保護它免受中斷處理程式的干擾。
今天的系統程式員仍然使用原始含義的“臨界區”,但現在我們有時也說它來談論一個執行緒執行的例程,而該執行緒具有互斥鎖鎖定。
IMO,“關鍵部分”鼓勵一種不太有用的方式來考慮互斥鎖,因為它從來都不是需要保護免受干擾的代碼。它始終與保護共享資料的完整性有關。有時,擔心定義臨界區的程式員可能會忽略這樣一個事實,即程式中可能有多個例程都訪問相同的共享資料。
IMO,這是面向物件的編程風格大放異彩的地方,因為如果將其封裝在某個物件的私有成員中并且只能通過物件的執行緒安全訪問,則更容易跟蹤需要保護的內容,公共方法。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/531158.html
上一篇:創建執行緒后如何獲取用戶輸入
