線程安全對於我們的設計工作異常重要

  什麼是線程安全

  線程安全在多線程編程時是一個比較重要的概念,我們下先來看下維基百科是如何定義這個概念的:

  https://en.wikipedia.org/wiki/Thread_safety

  Thread safety is a computer programming concept applicable to multi-threaded code. Thread-safe code only manipulates shared data structures in a manner that ensures that all threads behave properly and fulfill their design specifications without unintended interaction.

  意思是說:

  線程安全是應用於多線程代碼的一種計算機編程概念,它確保多個線程能夠按照程序的設計正確的訪問共享數據結構。

  或者再貼近編程語言的角度一點來講,線程安全指的是同時最少有兩個及以上的線程操作共享的數據區域,並且至少有一個是寫操作。如果你還想不明白,可以去衛生間觀察一下,一個廁位同時能有幾個人使用。

  線程安全的級別

  線程安全的級別或者粒度有三種,如下:

  (1)線程安全

  這種情況下其實沒有線程安全問題,比如上面的例子中,每個人都有自己專用的衛生間,所以不會存在競爭問題。

  (2)條件安全

  條件安全,顧名思義是有條件的,所有人共用幾個衛生間,搶到資源的就把門關上,通過門來隔離資源,後面的人就在外面等待直到裏面的人出來。

  (3)不安全

  這種情況下連門都沒有,所以並不能很好保證資源安全,所以這種情況最好不能讓同時讓多個人直接使用。

  實現線程安全的方式

  大體來說有兩種,首先我們明白安全問題來自於競爭,沒有競爭就不會有問題。

  方式一:

  核心思路是避免共享數據結構,共享狀態。包括:

  (1)使用線程local變量

  (2)使用不可變對象

  方式二:

  核心思路是共享不可避免,需要通過條件來確保按照。包括:

  (1)互斥鎖

  (2)CAS原子操作

  Java語言裏面實現策略

  這裏以Java語言爲例子,上面談到的4種方式,其實在Java裏面都支持,分別對應的解決手段爲:

  (1)ThreadLocal變量

  (2)不可變對象有String,CopyOnWrite集合類

  (3) 互斥鎖包括JDK5之前的內置鎖synchronized和JDK5之後的Lock接口

  (4) J.U.C裏面Atom開頭的類瀋陽做胃鏡多少錢 

  可以看出來Java裏面的處理策略還是比較多的,當然不同的策略其實也有具體的適用場景,此外引入了線程安全和同步手段會對代碼的性能造成一定的影響,這一點需要了解。

  一般來說避免共享數據結構是能夠比較優雅的解決併發問題,這種程序對多線程更友好,性能也會更高。比如單機的ThreadLocal和分佈式的Ator模型。這裏面不存在競爭。其次是不可變變量,多線程操作的都是CopyOnWrite,這也是爲什麼一些動態編程語言如Scala裏面的默認數據結構大多數都是不可變的。不可變有不可變的好處,但缺點也是明顯的,如果需要頻繁對數據修改,那麼會創建很多臨時對象和佔用更多的內存。

  上面這兩種場景,我們一般稱爲無鎖實現,性能很好。如果避免不了共享數據,那麼接着性能比較好的就是CAS這種原子操作,這種情況下我們一般也稱是無鎖的,但其實是利用了操作系統的原子指令來實現的,在競爭不激烈的場景下性能比較好,一般的編程語言都有封裝好的工具類。如果競爭激烈,其實性能未必比使用互斥鎖高。互斥鎖一般也稱重量級鎖,需要OS干涉線程的調度,適合用於競爭激烈的場景下,這種方式下線程上下文的交換會降級系統的性能,在使用時需要注意。

  線程併發技能圖譜

  多線程編程領域其實涉及很多計算機知識,線程安全只是其中的冰山一角,作爲一名技術人員我們有必要系統的學習和攻破併發編程這一塊,很多人覺得併發編程很難,其實是沒有掌握系統的學習方法,在這裏我放出我之前總結併發知識的一張圖譜

  總結

  本文主要介紹了什麼是線程安全,及實現線程安全的一些手段,並結合Java語言描述了相關的知識,最後又總結了Java裏面併發學習的知識圖譜,只要把裏面所有的內容都瞭解掌握,那麼在多線程領域就可以從青銅升級到王者段位了,不過學習之路,學無止境,不能急功近利,一定得重基礎,然後循序漸近,日拱一卒,就算慢點也無妨,堅持下去,肯定有所收穫。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章