2010-01-04 20 views
11

Threadsafe是圍繞文檔拋出的術語,但很少解釋它的含義,特別是對於第一次學習線程的人可以理解的語言。如何定義線程安全?

那麼你如何解釋Threadsafe代碼給一個新的線程? 我對選項的想法是當下是:

  • 你用的是什麼使代碼 線程安全與線程不安全的列表
  • 書中定義
  • 一個有用的比喻
+0

社區wiki? – Adrian 2010-01-04 13:44:06

回答

12

Eric Lippert says

當我問 「此代碼線程安全?」我總是不得不推回並詢問「什麼是您關心的確切線程場景?」和「」這些場景中的每個場景中對象的正確行爲是什麼?「。

如果說代碼是「線程安全」而沒有用某種方式傳達所利用的線程安全機制所做的和不能阻止的不良行爲是無益的。

3

G'day,

一個好的開始是讀一讀POSIX paper on thread safety

編輯︰只是前幾段給你一個線程安全和重入代碼的快速概述。

HTH

歡呼聲,

2

線程安全功能/對象(以下簡稱爲對象)是被設計成支持多個併發呼叫的對象。這可以通過序列化並行請求或某種對交織呼叫的支持來實現。基本上,如果對象安全地支持併發請求(來自多個線程),則它是線程安全的。如果它不是線程安全的,則多個併發呼叫可能會破壞其狀態。

考慮酒店的日誌。如果一個人在書中寫作,而另一個人出現並開始同時編寫他的消息,則最終結果將是兩個消息的混合。這也可以通過寫入輸出流的多個線程來演示。

+0

真的很好的例子 – 2010-01-07 06:27:08

0

胎記安全代碼是不會失敗的代碼,因爲相同的數據一次在兩處發生更改。線程安全是一個小於併發安全的概念,因爲它假定它實際上是同一個程序的兩個線程,而不是(比方說)修改數據的硬件或操作系統。

0

該術語的一個特別有價值的方面是它位於一系列併發行爲上,其中線程安全性最強,中斷安全性比線程安全性弱,並且可重入甚至更弱。

在線程安全的情況下,這意味着所討論的代碼符合一致的api並且使用資源,以便不同線程中的其他代碼(例如另一個線程的併發實例)不會導致不一致,只要它也符合相同的使用模式。必須指定使用模式,以保證線程安全的合理預期。

中斷安全約束通常不會出現在現代用戶態代碼中,因爲操作系統在隱藏這個方面做得非常好,但是在內核模式下這非常重要。這意味着即使在執行過程中觸發中斷,代碼也會成功完成。

最後一個,可重入的,幾乎可以保證所有現代語言,進出用戶區,這只是意味着一段代碼可能會被多次輸入,即使執行還沒有超出代碼段在較舊的情況下。例如,這可能發生在遞歸函數調用的情況下。通過訪問非重入代碼中的共享全局狀態變量來違反語言提供的重入是非常容易的。

+0

有兩個獨立的問題 - 第一個問題是,一個操作的嵌套實例是不是必須在第一個執行期間的任何時間點開始,或者是否可能發生在特定的允許點上,或者基本上是任意點;第二個是在原始動作恢復之前嵌套動作是否必須完成。因爲多任務處理非常流行,所以大多數可以啓動嵌套動作的例程將允許它與第一個併發運行,但它曾經是(並且在一些嵌入式環境中仍然存在)對於嵌套動作來說通用以保存第一個... – supercat 2012-08-26 15:38:47

+0

...當它進入時,並在退出時恢復它。在使用全局狀態的場景中,與具有多個活動狀態以及在它們之間切換的能力相比,此模式可能更容易處理。但是,它確實對可以執行的多任務處理的類型施加了一些限制。 – supercat 2012-08-26 15:40:52

14

多線程會導致非確定性執行 - 您無法確切知道何時運行某段並行代碼。

鑑於此,這個奇妙的multithreading tutorial定義線程安全這樣的:

線程安全的代碼是具有在任何多線程情況下的臉上沒有不確定性的代碼。線程安全主要通過鎖定來實現,並且通過減少線程之間交互的可能性來實現。

這意味着無論特別是如何運行線程,行爲總是定義明確的(因此不需要race conditions)。

3

我也許是錯的,但線程安全的標準之一是隻使用局部變量。如果從不同的線程調用相同的函數,則使用全局變量可能會導致未定義的結果。

+0

只有部分是真的,因爲你只需要用互斥體保護這些全局變量,例如具有線程安全功能 – claf 2012-05-14 17:55:02

+0

@claferri:我認爲問這個問題的意圖是要知道可能導致不安全線程的事情。你絕對可以使用同步對象(不只是互斥體,而是信號量/關鍵部分等)來使線程安全。我想指出導致線程不安全代碼的其中一個問題。反對票不被接受。 – 2012-05-15 21:26:36