什麼是線程安全的(thread-safe)? html
在java中,線程安全的指的是代碼能夠在併發的或者多線程的環境下安全的使用或者共享,而且它們都將按照指望的方式運行。任何代碼,類或者對象,若是它們在併發的環境中運行表現出的行爲與在非併發環境下表現出的行爲不一致,那麼它們就不能被稱爲線程安全的。 java
本片文章不會很是仔細的介紹線程安全或者Java中的異步處理,咱們將經過幾個例子來幫助你理解什麼是線程安全的而後告訴你如何讓你的代碼線程安全。 緩存
一個non-thread-safe的例子 安全
public class Counter { private int count; /* * 這個方法不是線程安全的,由於++操做不是原子操做 */ public int getCount(){ return count++; } }上面的例子不是線程安全的,由於++(自增操做)不是一個原子操做(atomic operation),而是會被拆分紅讀、更新和寫操做(read,update,write)三部分,若是多個線程大約在同一時刻調用getCount()方法,這三個操做可能會互相重合(coincide)或者重疊(overlap),好比:當thread1正在更新數據,thread2此時讀取數據,那他將會得到原來的舊數據,最後的結果就是thread2會覆蓋掉thread1對數據的增長操做,結果就是:一個數據被丟失了,就是由於程序是併發調用的。
如何在Java中實現線程安全? 多線程
要使上面的方法線程安全,能夠有不少種方式: 併發
1)使用synchronized關鍵字來鎖定getCount方法,以保證同一時刻只有一個線程能夠訪問getCount方法,這樣作就能避免重合(coincide)或者重疊(overlap)問題。 異步
2)使用AutomicInteger,這樣就將++變成了原子操做,由於原子操做是線程安全的,這樣作還節省了額外的同步操做的開銷。 ide
下面是一個實現線程安全的例子: 優化
public class Counter { private int count; AtomicInteger atomicCount = new AtomicInteger( 0 ); /* * 如今這個方法是線程安全的,由於增長了synchronized */ public synchronized int getCount(){ return count++; } /* *這個方法是線程安全的,由於count的增長操做是原子操做 */ public int getCountAtomically(){ return atomicCount.incrementAndGet(); } }關於Thread-Safe的一些重要的點:
這些點在你寫線程安全的程序的時候是頗有用的,並且也能幫你避免一些很嚴重的併發問題,好比:競爭條件(race condition)或者死鎖 atom
1)不可變的對象(immutable objects)默認就是線程安全的,由於它們的狀態一旦建立就不能被改變。因爲字符串在Java中就是不可變的,因此它們本來就是線程安全的(關於不可變對象,後期會有相關文章進行說明)。
2)只讀的或者被final修飾的變量也是線程安全的。
3)鎖機制在Java中是一種實現線程安全的方式。
4)靜態變量若是沒有被正確的synchronized,那麼它將成爲線程安全問題的主要緣由。
5)Java中的一些線程安全的例子:Vector, Hashtable, ConcurrentHashMap, String等。
6)Java中的原子操做是線程安全的,好比從內存中讀取一個32位的int值是線程安全的,由於它是原子操做,因此不會與其餘線程交錯。
7)局部變量也是線程安全的,由於每個線程都會有屬於她本身的一份拷貝。使用局部變量是一種很好的實現線程安全的方式。
8)爲了實現線程安全,儘量地減小多個線程中對象的共享。
9)volatile關鍵字能夠用來指示線程不緩存該變量而是直接從主內存中讀取,也能夠指示JVM不從多線程的角度來從新排序或者優化代碼(not to reorder or optimize code from threading perspective)。
以上就是本文介紹的一些內容。
線程安全是一個比較難以掌握的概念,爲了肯定程序是否線程安全你須要考慮多併發的狀況,另外JVM爲了會對代碼進行優化,而優化的過程就會涉及到對代碼的從新排序,因此看起來是串行的程序在開發環境中運行良好,但並不能保證在生產環境中會一樣良好,由於JVM會盡最大可能的進行調整,從而進行一些代碼重排序和優化,這樣就會致使線程安全的問題。
參考資料:http://javarevisited.blogspot.com/2012/01/how-to-write-thread-safe-code-in-java.html
----------------------------------------------------------------
小人不才,若有問題,歡迎各位不吝賜教!