如何设计java线程安全类_如何设计线程安全的Java程序
什么是線程安全的(thread-safe)?
在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,這樣就將++變成了原子操作,因為原子操作是線程安全的,這樣做還節省了額外的同步操作的開銷。
下面是一個實現線程安全的例子:
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)或者死鎖
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會盡最大可能的進行調整,從而進行一些代碼重排序和優化,這樣就會導致線程安全的問題。
----------------------------------------------------------------
小人不才,如有問題,歡迎各位不吝賜教!
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的如何设计java线程安全类_如何设计线程安全的Java程序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 站长平台怎么添加网站(站长平台怎么添加网
- 下一篇: java美元兑换,(Java实现) 美元