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代碼塊的調用,不會影響代碼塊中任何一個變量,對象,以及括號內對象的調用,以及讀寫操作。