詳解java修飾符synchronized

synchronized會以兩種形式出現在代碼中

1.synchronized(對象){}代碼塊形式

這種形式下,鎖是加在括號內的對象上,所以你只需要看括號裏面的對象指向的堆內存地址,如果內存地址相同,就會互斥,如果內存地址不同,就可以併發調用。

簡單地用代碼表示一下:

class Xxx{
		static String demo = " ";
		synchronized(demo){
		}
	}

對於以上代碼,所有xxx類的對象訪問的demo都是同一個內存地址:

比如:

Xxx x1 = new Xxx();
x1.demo;
Xxx x2 = new Xxx();
x2.demo;
x1和x2調用的demo其實是同一個,所以當x1調用該代碼塊時,x2再調用會發現demo上有鎖,只能等待x1調用完畢再調用。

class Xxx{
		String demo = " ";
		synchronized(demo){
		}
	}

相反,如果demo沒有static修飾,synchronized鎖只會對同一個對象起作用,不同對象可以併發訪問。

Xxx x1 = new Xxx();
x1.demo;
Xxx x2 = new Xxx();
x2.demo;
在這幾行代碼中,x1和x2所調用的demo是分別保存在兩個內存地址中,當x1調用synchronized代碼塊時,x2再調用,會發現,自己的demo上沒有鎖,所以兩個對象可以併發調用。

還有一種特殊情況,synchronized(xxx.class){}這種情況也是對這個類的所有對象起作用的。

2.synchronized 方法名()方法形式

其實修飾方法和代碼塊形式也是差不多的,如果方法有static修飾,就對該類的所有對象起作用,相反,如果是個動態方法,則只會對同一對象起作用,不同對象可以併發執行。

下面簡單敘述一下原理,當有線程執行synchronized代碼塊時,鎖的標誌是加在括號內的對象上的。當有線程再調用它時,會檢查括號內對象鎖的狀態,所以當兩次調用括號內對象指向不同內存時,是不影響併發執行的。

強調一點,鎖加在對象上,只是限制synchronized代碼塊的調用,不會影響代碼塊中任何一個變量,對象,以及括號內對象的調用,以及讀寫操作。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章