併發編程筆記二:synchronized鎖住了誰?

在併發編程中要使用到關鍵字synchronized,當咱們用synchronized關鍵字修飾一個方法時,表明着一個鎖(Lock),那麼這個鎖的對象是什麼,也就是它鎖住了誰?編程

synchronized的使用狀況大概就是下面幾種:安全

  • synchronized修飾非靜態方法
  • synchronized修飾靜態方法
  • 同步代碼塊的synchronized (this)
  • 同步代碼塊的synchronized (非this對象)
  • 同步代碼塊的synchronized (類.class)

實際上,synchronized修飾非靜態方法、同步代碼塊的synchronized (this)用法和synchronized (非this對象)的用法鎖的是對象,線程想要執行對應同步代碼,須要得到對象鎖。併發

synchronized修飾靜態方法以及同步代碼塊的synchronized (類.class)用法鎖的是類,線程想要執行對應同步代碼,須要得到類鎖。ide

看下面代碼:this

public class MultiThread {

	private static int num = 0;
	
	/** static */
	public  synchronized void printNum(String tag){
		try {
			
			if(tag.equals("a")){
				num = 100;
				System.out.println("tag a, set num over!");
				Thread.sleep(1000);
			} else {
				num = 200;
				System.out.println("tag b, set num over!");
			}
			
			System.out.println("tag " + tag + ", num = " + num);
			
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	//注意觀察run方法輸出順序
	public static void main(String[] args) {
		
		//倆個不一樣的對象
		final MultiThread m1 = new MultiThread();
		final MultiThread m2 = new MultiThread();
		
		Thread t1 = new Thread(new Runnable() {
			@Override
			public void run() {
				m1.printNum("a");
			}
		});
		
		Thread t2 = new Thread(new Runnable() {
			@Override 
			public void run() {
				m2.printNum("b");
			}
		});		
		
		t1.start();
		t2.start();
		
	}
}

printNum方法加了synchronized 關鍵字,根據輸入參數不一樣打印不一樣信息,當咱們執行main方法時,發現貌似synchronized沒起做用。控制檯輸入以下:線程

tag a, set num over!
tag b, set num over!
tag b, num = 200
tag a, num = 200

這是由於synchronized 鎖住的是對象,線程t1t2分別獲取的是m1,m2的鎖,他們並無在獲取鎖上有競爭關係,所以,出現非同步的結果。code

那若是要讓printNum方法在多個對象之間也是線程安全的呢,一個對象在執行這個方法時,其餘對象必須阻塞等待,一次只能有一個對象能執行這個方法。只須要加個static關鍵字來修飾printNum方法,這時synchronized 關鍵字鎖住的就是MultiThread 的.class類了。對象

public static synchronized void printNum(String tag)
...

這時的輸出結果就符合咱們的預期了同步

tag b, set num over!
tag b, num = 200
tag a, set num over!
tag a, num = 100
相關文章
相關標籤/搜索