不同鎖互不影響,共用一個鎖,可能會發生阻塞。
1.在修飾靜態方法時,鎖定的是當前類的 Class 對象,在下面的例子中就是SycTest1.class
?2.當修飾非靜態方法時,鎖定的就是 this 對象,即當前的實例化對象
public class SyncTest1 {// synchronized修飾非靜態方法public synchronized void test1() {for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName() + " : " + i);try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}}// synchronized修飾this對象,即當前的實例化對象public void test2() {synchronized (this) {for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName() + " : " + i);try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}}}public static void main(String[] args) {SyncTest1 t1 = new SyncTest1();new Thread(new Runnable() {@Overridepublic void run() {t1.test1();}}, "thread1").start();new Thread(new Runnable() {@Overridepublic void run() {t1.test2();}}, "thread2").start();}
}
thread1 : 0
thread1 : 1
thread1 : 2
thread1 : 3
thread1 : 4
thread2 : 0
thread2 : 1
thread2 : 2
thread2 : 3
thread2 : 4
通過上面代碼中可以看到,在test1里修飾的是非靜態方法,即鎖定的為當前實例化對象,即對象鎖,test2鎖定的就是this對象,也是對象鎖,也就是thread1和thread2請求的是同一把鎖,所以是Thread1運行完之后Thread2才運行。?
public class SyncTest1 {// 修飾靜態方法public static synchronized void test1() {for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName() + " : " + i);try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}}// 修飾類對象public void test2() {synchronized (SyncTest1.class) {for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName() + " : " + i);try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}}}public static void main(String[] args) {SyncTest1 t1 = new SyncTest1();new Thread(new Runnable() {@Overridepublic void run() {SyncTest1.test1();}}, "thread1").start();new Thread(new Runnable() {@Overridepublic void run() {t1.test2();}}, "thread2").start();}
}
thread1 : 0
thread1 : 1
thread1 : 2
thread1 : 3
thread1 : 4
thread2 : 0
thread2 : 1
thread2 : 2
thread2 : 3
thread2 : 4
通過上面代碼中可以看到,在test1里修飾的是靜態方法,即鎖定的為當前的類對象,即類鎖,而test2鎖定的SyncTest1.class,也是類鎖,也就是thread1和thread2請求的是同一把鎖,所以是Thread1運行完之后Thread2才運行。??
public class SyncTest1 {// 修飾靜態方法public static synchronized void test1() {for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName() + " : " + i);try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}}// 修飾非靜態方法public synchronized void test2() {for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName() + " : " + i);try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {SyncTest1 t1 = new SyncTest1();new Thread(new Runnable() {@Overridepublic void run() {SyncTest1.test1();}}, "thread1").start();new Thread(new Runnable() {@Overridepublic void run() {t1.test2();}}, "thread2").start();}
}
thread1 : 0
thread2 : 0
thread1 : 1
thread2 : 1
thread2 : 2
thread1 : 2
thread2 : 3
thread1 : 3
thread2 : 4
thread1 : 4
通過上面代碼中可以看到,在test1里修飾的是靜態方法,即鎖定的為當前的類對象,即類鎖,而test2鎖定的非靜態方法,也就是對象鎖,也就是thread1和thread2請求的不是同一把鎖,所以他們是兩個鎖,互不影響。
對象鎖與類鎖的區別:
對象鎖和類鎖其實本質上都是一種鎖,區別在于一個類可以有多個對象鎖,但類鎖只有一個。 故使用 synchronized 對類加鎖是唯一的,當一個線程拿到類鎖,其他線程在執行到任何需要類鎖的方法時都將阻塞。?總體來說類鎖具有唯一性。
類的實例化對象可以有多個,對每個實例化對象加鎖是互不干擾的,它們不具備全局唯一性,這里我們稱它為對象鎖。
對象鎖一般可以用于細粒度鎖的創建。
借鑒:Java并發編程-類鎖與對象鎖剖析 - 掘金?
synchronized的對象鎖和類鎖的區別 - 掘金
近日總結:感冒了......emo......
?