1. 程式人生 > >靜態synchronized方法和非靜態synchronized方法的鎖物件不是同一個

靜態synchronized方法和非靜態synchronized方法的鎖物件不是同一個

靜態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也不會產生競爭,結果是和上面的一樣的