在併發編程中要使用到關鍵字synchronized
,當咱們用synchronized
關鍵字修飾一個方法時,表明着一個鎖(Lock),那麼這個鎖的對象是什麼,也就是它鎖住了誰?編程
synchronized
的使用狀況大概就是下面幾種:安全
實際上,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
鎖住的是對象,線程t1
,t2
分別獲取的是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