不少時候,咱們並不知道在什麼狀況下使用線程同步。在錯誤的狀況下,就會影響性能。在正確的狀況下,咱們就能夠防止程序出現錯誤。是數據的安全獲得保證。java
線程同步通常使用在共享數據狀況下,就是說共享數據,須要使用線程同步進行保護起來,使數據的安全獲得保證。好比:在電子商務中,商品的庫存,是共享的數據。數據庫
相對於synchronized來講,volatile是比較輕量級的線程同步鎖。synchronized通常使用在函數上。好比:安全
public synchronized int get() {return value;}
而Volatile變量,用來確保將變量的更新操做通知到其它線程。當把變量聲明爲Volatile類型後,編譯器與運行時都會注意到這個變量是共享的。函數
Volatile變量一般用作某個操做完成、發生中斷或者狀態的標誌。Volatile的語義不足以確保遞增操做(count++)的原子性,除非你能確保只有一個線程對變量執行寫操做。好比:性能
volatile boolean asleep; while(!asleep) conutSome();
當訪問共享的可變數據時,一般須要使用同步。一種避免使用同步的方式就是不共享數據。若是僅在單線程內訪問數據,就不須要同步。這種技術被稱爲線程封閉。線程封閉技術有兩種:一棧封閉;二是ThreadLocal類。這篇文章只講講第二種的應用,由於是咱們常用的。spa
ThreadLocal對象一般用於防止對可變的單實例變量或全局變量進行共享。好比,在單線程應用程序中可能會維持一個全局的數據庫鏈接。因此,通常使用在JDBC中,經過將JDBC的連接保存到ThreadLocal對象中,每一個線程都會擁有屬於本身的連接。 線程
public class DBContextHolder { private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>(); public static void setDBType(String dbType) { contextHolder.set(dbType); } public static String getDBType() { return contextHolder.get(); } public static void clearDBType() { contextHolder.remove(); } }
調用:code
public class DynamicDataSource extends AbstractRoutingDataSource { // 查找當前用戶上下文變量中設置的數據源 protected Object determineCurrentLookupKey() { return DBContextHolder.getDBType();//這裏調用 } // 設置默認的數據源 public void setDefaultTargetDataSource(Object defaultTargetDataSource) { super.setDefaultTargetDataSource(defaultTargetDataSource); } // 設置數據源集合. public void setTargetDataSources(Map targetDataSources) { super.setTargetDataSources(targetDataSources); } }
當某個頻繁執行的操做須要一個臨時對象,例如一個緩衝區,而同時又但願避免在每次執行時都從新分配該臨時對象,就可使用這項技術。對象
在線程同步中,有三種性質:可見性、原子性、不變性。前面的synchronized能夠確保原子性,而Volatile能夠確保可見性。那麼不變性,就用Final域來進行講解。不變性主要使對象具備不可變,進而得出:不可變對象必定是線程安全的。但不可變性並不等於將對象中全部的域都聲明爲final類型,即便對象中全部的域都爲final類型的,這個對象也仍然是可變的,由於在final類型的域中能夠保存對可變對象的應用。rem
當知足如下條件時,對象纔是不可變的:
1.對象建立之後其狀態就不能修改。2.對象的全部域都是final類型。3.對象是正確建立的。
不少時候,咱們是直接調用Java Jdk原有的類,進行對數據的包裝,進而使數據達到線程同步。如下線程安全庫中的容器類提供了一下的安全發佈保證:
1.經過將一個鍵或者值放入Hashtable、synchronizedMap或者ConcurrentMap中,能夠安全地將它發佈給如何從這些容器中訪問它的線程。
2.經過將某個元素放入Vector、CopyOnWriteArrayList、CopyOnWriteArraySet、synchronizedList或synchronizedSet中。
3.經過將某個元素放入BlockingQuete或者ConcurrentLinkedQueue中。