用關鍵字synchronized聲明方法是有弊端的。java
synchronized同步代碼塊的使用:當兩個併發線程訪問桶一個對象object中的synchronized(this)同步代碼塊是,一段時間內只能有一個線程被執行,另外一個線程必須等待當前線程執行完這個代碼塊之後才能執行該代碼塊。緩存
synchronized(this){ }
當一個線程訪問object的一個synchronized同步代碼塊時,另外一個線程仍然能夠訪問該object對象中的非synchronized(this)同步代碼塊。所以能夠較同步方法提升效率。多線程
object對象中的代碼,不在synchronized塊中就是異步執行,在synchronized塊中就是同步執行。併發
synchronized代碼塊之間的同步性:在使用synchronized(this)同步代碼塊時須要注意的是,當一個線程訪問object的一個synchronized(this)同步代碼塊時,其餘線程對同一個object中全部其餘synchronized(this)同步代碼塊的訪問將被阻塞,這說明synchronized使用的對象監視器是同一個。必須等待當前synchronized(this)同步代碼塊執行完以後,才能訪問其餘的synchronized(this)同步代碼塊。異步
同synchronized方法同樣,synchronized(this)同步代碼塊也是鎖定當前對象的。工具
將任意對象做爲對象監視器this
6.1 多個線程調用同一個對象的不一樣名稱的synchronized同步方法或synchronized(this)同步代碼塊是,調用的效果就是按順序執行,同步的,阻塞的。線程
6,2 synchronized代碼塊支持對任意對象做爲對象監視器來實現同步的功能,大可能是實例變量及方法參數。使用方法爲synchronized(非this對象 x){}code
在多個線程持有的對象監視器爲同一個對象的前提下,同一時間只有一個線程能夠執行synchronized(非this對象 x)同步代碼塊中的代碼。對象
6.3 鎖非this對象具備好處:synchronized(非this對象)同步代碼塊與同步方法和synchronized(this)同步代碼塊是異步的,不會與其餘鎖this同步方法爭搶this鎖,則可大大提升運行效率。
6.4 使用synchronized(非this對象)同步代碼塊進行同步操做時,對象監視器必須是同一個對象,不然就有多把鎖,結果爲異步運行。
6.5使用synchronized(非this對象)同步代碼塊能夠避免髒讀問題。
synchronized(非this對象 x)同步代碼塊是將x對象自己做爲「對象監視器」,這樣就有如下三個結論:
1)當多個線程同時執行synchronized(x)同步代碼塊時呈同步效果;
2)當其餘線程執行x對象中的synchronized同步方法時呈同步效果;
3)當其餘線程執行x對象方法裏的synchronized(this)代碼塊時也呈同步效果。
靜態同步synchronized方法與synchronized(class)代碼塊
關鍵字synchronized能夠應用在static靜態方法上,即對當前的*.Java文件對應的Class類進行持鎖。synchronized關鍵字加到靜態方法上是給Class類上鎖,而synchronized關鍵字加到非static方法上是給對象上鎖。
Class鎖能夠對類的全部對象實例起做用。
同步synchronized(class)代碼塊與synchronized static方法的做用同樣。synchronized(Service。class)。
數據類型String的常量池特性
1)在JVM中具備常量緩存池的功能
String a = "A"; String b = "A"; System.out.println(a == b); 輸出結果爲:true
將synchronized(string)同步塊與String聯合使用時,要注意常量池帶來的一些例外。如線程A和線程B持有的鎖都是「aa」,因爲「aa」的緩存池屬性,他們持有的是同一個鎖,因此有可能其中一個線程永遠沒法執行。
多線程的死鎖
死鎖:不一樣的線程都在等待根本不願被釋放的鎖,從而致使全部的任務都沒法繼續完成。
public void run(){ if(username.equals("a")){ synchronized(lock1){ //todo synchronized(lock2){ //todo } } } if(username.equals("b")){ synchronized(lock2){ //todo synchronized(lock1){ //todo } } } }
可使用JDK自帶的工具來檢測是否有死鎖的現象:1)jps--查詢出線程id號;2)jstack -l 線程id號 --列出Java stack信息。
內置類與靜態內置類
1)內置類中有兩個同步方法,但使用不一樣的鎖,則運行結果是異步的。
鎖對象的改變
在將任何數據類型做爲同步鎖時,須要注意的是,是否有多個線程同時持有鎖對象,若是同時持有相同的鎖對象,那麼這些線程之間就是同步的,若是分別得到鎖對象,這些線程之間就是異步的。
只要對象不變,即便對象的屬性被改變,運行的結果仍是同步的。