線程同步詳細講解

1、什麼狀況下使用線程同步

           不少時候,咱們並不知道在什麼狀況下使用線程同步。在錯誤的狀況下,就會影響性能。在正確的狀況下,咱們就能夠防止程序出現錯誤。是數據的安全獲得保證。java

            線程同步通常使用在共享數據狀況下,就是說共享數據,須要使用線程同步進行保護起來,使數據的安全獲得保證。好比:在電子商務中,商品的庫存,是共享的數據。數據庫

2、Volatile變量

            相對於synchronized來講,volatile是比較輕量級的線程同步鎖。synchronized通常使用在函數上。好比:安全

public synchronized int get() {return value;}

而Volatile變量,用來確保將變量的更新操做通知到其它線程。當把變量聲明爲Volatile類型後,編譯器與運行時都會注意到這個變量是共享的。函數

            Volatile變量一般用作某個操做完成、發生中斷或者狀態的標誌。Volatile的語義不足以確保遞增操做(count++)的原子性,除非你能確保只有一個線程對變量執行寫操做。好比:性能

volatile boolean asleep;

while(!asleep)
   conutSome();

3、線程封閉

            當訪問共享的可變數據時,一般須要使用同步。一種避免使用同步的方式就是不共享數據。若是僅在單線程內訪問數據,就不須要同步。這種技術被稱爲線程封閉。線程封閉技術有兩種:一棧封閉;二是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);
	}
}

            當某個頻繁執行的操做須要一個臨時對象,例如一個緩衝區,而同時又但願避免在每次執行時都從新分配該臨時對象,就可使用這項技術。對象

4、不變性

            在線程同步中,有三種性質:可見性、原子性、不變性。前面的synchronized能夠確保原子性,而Volatile能夠確保可見性。那麼不變性,就用Final域來進行講解。不變性主要使對象具備不可變,進而得出:不可變對象必定是線程安全的。但不可變性並不等於將對象中全部的域都聲明爲final類型,即便對象中全部的域都爲final類型的,這個對象也仍然是可變的,由於在final類型的域中能夠保存對可變對象的應用。rem

            當知足如下條件時,對象纔是不可變的:

            1.對象建立之後其狀態就不能修改。2.對象的全部域都是final類型。3.對象是正確建立的。

5、Java中有哪些類是線程同步的

            不少時候,咱們是直接調用Java Jdk原有的類,進行對數據的包裝,進而使數據達到線程同步。如下線程安全庫中的容器類提供了一下的安全發佈保證:

            1.經過將一個鍵或者值放入Hashtable、synchronizedMap或者ConcurrentMap中,能夠安全地將它發佈給如何從這些容器中訪問它的線程。

            2.經過將某個元素放入Vector、CopyOnWriteArrayList、CopyOnWriteArraySet、synchronizedList或synchronizedSet中。

            3.經過將某個元素放入BlockingQuete或者ConcurrentLinkedQueue中。

相關文章
相關標籤/搜索