Java 并發 – 線程安全?

簡書 賈小強
轉載請注明原創出處,謝謝!

線程安全的定義常常讓人迷惑,搜索引擎會發現無數定義,比如:

  1. 多個線程同時執行也能正確工作就是線程安全的代碼
  2. 多個線程同時執行能以正確的方式操縱共享數據就是線程安全的代碼。
    而且還有很多類似的定義

你是否認為這種定義實際上沒有任何意義而且還讓人更加迷惑?雖然這些定義沒錯,但事實是他們沒有提供任何實際的幫助或觀點。我們如何區分線程安全類和不安全類?我們所謂的“安全”是什么意思?

線程安全的正確性是什么?

線程安全的任何合理定義的核心是正確性的概念。因此,在了解線程安全之前,我們首先應該理解這個“正確”。

正確性意味著一個類符合它的規范。

一個好的類規范將在任何給定的時間擁有關于一個類的狀態的所有信息,在其上執行某些操作以及它的后置條件。但我們經常沒有為我們的類寫出足夠的規范,我們怎么可能知道它們能正確的使用呢?我們不能,但這并不能阻止我們使用它們,一旦我們說服自己“代碼有效”。這種“代碼自信”來自于我們接近正確。

樂觀地將“正確性”定義為可以被識別的東西,現在我們可以用一種不那么繞的方式定義線程安全:當一個類在從多個線程訪問時繼續正常運行時,它是線程安全的。

不管運行時環境線程調度如何交織,只有當從多個線程訪問它行為正確,以及調用代碼的部分沒有額外的同步或其他協調,那么這個類是線程安全的

如果這個寬泛的“正確性”讓你覺得比較煩,那么您可能會認為線程安全類是一個在并發環境中比單線程環境中更糟的類。線程安全類封裝了所需的同步,這樣客戶端就不必提供自己的同步。

示例:無狀態servlet

線程安全類的一個很好的例子是java servlet沒有字段(fields)和引用(references),沒有來自別的類的字段,它們是無狀態的。

public class StatelessFactorizer implements Servlet 
{
    public void service(ServletRequest req, ServletResponse resp) 
    {
        BigInteger i = extractFromRequest(req);
        BigInteger[] factors = factor(i);
        encodeIntoResponse(resp, factors);
    }
}

在特定計算瞬間數據僅存儲在正在在執行線程的堆棧上,即局部變量。一個線程訪問一個statelessfactorizer不會影響另一個線程訪問同一個statelessfactorizer產生的結果;因為兩個線程不共享狀態,就好像他們訪問不同的實例。由于某個線程對無狀態對象的的訪問操作不會影響其他線程中操作的正確性,無狀態對象是線程安全的。

這就是圍繞線程安全的這個小而重要的概念

Happy Learning !!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 處理器的時鐘頻率已經很難再提高,想要提升計算機的性能,一個很明顯的趨勢是使用多處理器。因為程序調度的基本單元是線程...
    w1992wishes閱讀 174評論 0 0
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,455評論 25 708
  • 2017-03-13 青汁知識----什么是膳食纖維 膳食纖維是一種多糖,它既不能被胃腸道消化吸收,也不能產生能量...
    螞蟻農場青汁閱讀 878評論 0 1
  • 和菜頭最近寫了篇 “大公司的活死人“,他說選擇大公司對于許多人來說是一種本能,和理性判斷全無關系,只是和人性中根深...
    茗姐說閱讀 548評論 0 0
  • “王童鞋,我回家了,回家相親,你要照顧好自己!”這是莫小雨出發前發給我的短信,看到后百感交集!時間過的真快,不知道...
    薩迪噶閱讀 793評論 0 1