我看到在處理多執行緒時有很多方法可以避免競爭條件,但最常見的是互斥鎖和佇列。只要執行緒可能以混亂的順序填充佇列,我無法理解佇列如何使應用程式執行緒安全。
uj5u.com熱心網友回復:
只要執行緒可能以混亂的順序填充佇列,我無法理解佇列如何使應用程式執行緒安全。
首先,讓我們擺脫“執行緒安全”。“執行緒安全”實際上只應該用于描述可用于構建應用程式的組件(函式、模塊、類、庫等)。
如果一個組件在被多個執行緒同時使用時,它保證以某種有用且有據可查的方式運行,那么它就是執行緒安全的。由于您在談論佇列,因此您可能對執行緒安全佇列的期望如下:
- 進入佇列的每個專案
put()最終都可以take()從佇列中取出。 - 沒有任何專案可以是
take()en that was notput()。 - * IF * 程式將兩個專案按一定順序放入佇列中,那么它們將按
take()相同的順序排列,
但,
- 如果程式允許并發
put()呼叫佇列,則佇列不能保證這些專案實際出現在佇列中的順序。
“執行緒安全”并不真正適用于應用程式,因為應用程式的用戶無法選擇是以多執行緒方式還是以單執行緒方式使用它。該選擇由應用程式作者決定。應用程式要么是正確的(它按預期作業),要么不是。
所以,讓我們重新陳述你的問題:
只要執行緒可能以混亂的順序填充佇列,我無法理解佇列如何使應用程式正確。
它不能。如果應用程式依賴于put()以某種特定順序進入佇列的物件,則應用程式程式員有責任確保put()呼叫不重疊。如果允許呼叫重疊,則佇列不可能知道應用程式程式員打算讓專案進入佇列的順序。
uj5u.com熱心網友回復:
在并發系統中,(撇開執行緒優先級不談),作業系統調度程式決定接下來在(多個)CPU 內核上調度哪些當前可運行的執行緒。它試圖做到“公平”,以免使某些不幸的執行緒餓死,同時偏袒其他執行緒。當然,在實時作業系統(例如 QNX)中,還有更多的細節,增加了這個簡單的概念。
因此,在這樣的系統中,不可能推斷“誰先來”,因為從應用程式的角度來看,調度程式的決定似乎是隨機的(但公平)。
因此,如果有人試圖創建一個“更好”的佇列,他們可能會考慮使用優先級佇列,并使用時間戳來對佇列內容進行排序。但是 - 由于每個執行緒都獲得一個時間戳(無論如何假設解析度足夠高),從應用程式的角度來看,它再次只是“隨機”的,哪個執行緒將首先出現。
哪種 - 哪種是證明,無論是否排隊 - 這個問題無法解決。
順便說一句,與具有 N 個中斷源的 cpu 相同,這些中斷源會同時更改其邏輯級別。硬體優先級或處理這些中斷的順序取決于中斷架構(每個中斷的中斷向量還是帶有軟體調度的單個中斷向量?)、線路噪聲、每個輸入的電氣特性的可變性等。
如何解決這個問題?您需要有一些三元方法(x, [y,z,t], u),而不是嚴格排序(x 在 y 之前),其中 - 根據您的應用程式要求,您有“同時性”的概念。即 x 先出現,然后 y,z,t 同時出現(在定義的時間間隔內),然后是 u。
此外,讓您的執行緒以無環有向圖的形式排列,例如裝配線上的小步驟,而不是某些事件形成一些反饋回圈,這有助于避免“高階”競爭條件。
就像在 www 中一樣,向作業執行緒發出冪等請求也有幫助。(a,b) -> ((a,b),c)用答案回傳問題是避免混淆的另一個技巧。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/481902.html
上一篇:boost::unordered_map<int,struct>和shared_mutex的執行緒安全
下一篇:開放MP。兩個連續回圈的并行化
