對象鎖
在 Java 中,每個對象都會有一個 monitor 對象,這個對象其實就是 Java 對象的鎖,通常會被稱為“內置鎖”或“對象鎖”。
類的對象可以有多個,所以每個對象有其獨立的對象鎖,互不干擾。
以下代碼鎖的均是對象鎖:
//對象鎖,鎖的是一個代碼塊 public void test(){ //do something... synchronized(this|object) { //當這里鎖的是this,那么和下面的那個方法用的是同一個鎖 } //do something... } //對象鎖,鎖的是一個方法 public synchronized void test(){ //do something... //do something... //do something... }
類鎖
在 Java 中,針對每個類也有一個鎖,可以稱為“類鎖”,類鎖實際上是通過對象鎖實現的,即類的 Class 對象鎖。
每個類只有一個 Class 對象,所以每個類只有一個類鎖。
//類鎖,鎖的是一個代碼塊 public void test(){ //do something... synchronized(類.class) { } //do something... } //類鎖,鎖的是一個方法 public static synchronized void test(){ //do something... //do something... //do something... }
對象鎖,類鎖,鎖static變量 之間的干擾性
- 不同的對象鎖,互相不干擾,可以並行
- 對象鎖和類鎖,互相不干擾,可以並行
- 鎖static變量很具有迷惑性,其實鎖的還是一個對象,依舊是對象鎖。類鎖只有上述的兩種情況,鎖static變量不是類鎖之一。因此下面兩個方法,依舊可以並行。
錯誤的加鎖和原因分析
synchronized 鎖的對象,要保證是不變的。一旦中途被改變,那么將失去鎖的意義。多線程競爭的就不是同一對象的鎖了。
原因:雖然我們對 i 進行了加鎖,但是
但是當我們反編譯這個類的 class 文件后,可以看到 i++實際是,
本質上是返回了一個新的 Integer 對象。也就是每個線程實際加鎖的是不同 的 Integer 對象。因此並不能起到鎖的作用。