靜態synchronized方法和非靜態synchronized方法的鎖物件不是同一個
阿新 • • 發佈:2019-02-04
靜態synchronized方法的鎖是Java檔案對應的Class物件,而非靜態synchronized方法的鎖是是個例項物件,這兩個鎖並不是同一個,因此靜態synchronized方法和非靜態synchronized方法之間不會相互干擾
驗證
public class Service { synchronized public static void printA() { //Class鎖 try { System.out.println("執行緒"+Thread.currentThread().getName()+"進入printA"); Thread.sleep(2000); System.out.println("執行緒" +Thread.currentThread().getName()+"離開printA"); } catch (InterruptedException e) { e.printStackTrace(); } } synchronized public static void printB() { //Class鎖 try { System.out.println("執行緒"+Thread.currentThread().getName()+"進入printB"); Thread.sleep(2000); System.out.println("執行緒" +Thread.currentThread().getName()+"離開printB"); } catch (InterruptedException e) { e.printStackTrace(); } } synchronized public void printC() { //物件鎖 try { System.out.println("執行緒"+Thread.currentThread().getName()+"進入printC"); Thread.sleep(2000); System.out.println("執行緒" +Thread.currentThread().getName()+"離開printC"); } catch (InterruptedException e) { e.printStackTrace(); } } }
public class ThreadA extends Thread{
public void run() {
Service.printA();
}
}
public class ThreadB extends Thread{
public void run() {
Service.printB();
}
}
public class ThreadC extends Thread{ private Service service; public ThreadC(Service service) { this.service = service; } public void run() { service.printC(); } }
public static void main(String[] args) { Service service = new Service(); ThreadA threadA = new ThreadA(); threadA.setName("A"); threadA.start(); ThreadB threadB = new ThreadB(); threadB.setName("B"); threadB.start(); ThreadC threadC = new ThreadC(service); threadC.setName("C"); threadC.start(); }
執行緒threadA和執行緒threadB是競爭同一個Class鎖,threadC是例項鎖,執行的結果是
執行緒A進入printA
執行緒C進入printC
執行緒A離開printA
執行緒C離開printC
執行緒B進入printB
執行緒B離開printB
可以看出,並不是同一個鎖,即使執行緒threadA和執行緒threadB的run方法是通過例項呼叫的靜態synchronized方法,鎖仍然是Class物件,而不是例項
public class ThreadA extends Thread{
private Service service;
public ThreadA(Service service) {
this.service = service;
}
public void run() {
try {
Thread.sleep(2000);
service.printA();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
這次threadA是通過service的例項呼叫靜態synchronized方法,和threadC也不會產生競爭,結果是和上面的一樣的