synchronized是Java中的關鍵字,是一種同步鎖 它能夠用來修飾方法和代碼塊多線程
多線程的狀況下 synchronized 修飾的方法和代碼塊會讓一個線程執行(鎖住代碼),另外的線程等待ide
下面咱們經過一個例子來看下spa
public class Synchronized { public void test(String tag) { if ("a".equals(tag)) { System.out.println("a"); } else if ("b".equals(tag)) { System.out.println("b"); } System.out.println("當前線程:"+Thread.currentThread().getName()); System.out.println("the end"); } public static void main(String[] args) { // TODO Auto-generated method stub final Synchronized s1 = new Synchronized(); final Synchronized s2 = new Synchronized(); Thread t1 = new Thread(new Runnable(){ @Override public void run() { // TODO Auto-generated method stub s1.test("a"); } },"t1"); Thread t2 = new Thread(new Runnable(){ @Override public void run() { // TODO Auto-generated method stub s2.test("b"); } },"t2"); t1.start(); t2.start(); } }
啓動兩個線程 調用方法 test 運行結果是這樣的 這是沒加synchronized 關鍵字的狀況,線程
(屢次運行結果可能不一樣)code
a 當前線程:t1 b 當前線程:t2 the end the end
這個結果表示一個線程不會等到另外一個線程執行完再執行對象
若是是一個線程等待另外一個線程執行完的話 打印結果應該是get
a
當前線程:t1
the end
b
當前線程:t2
the end同步
或者 class
b
當前線程:t2
the endtest
a
當前線程:t1
the end
下面 咱們在 test方法上加 synchronized 關鍵字看下打印結果
public class Synchronized { // 加 synchronized 修飾 public synchronized void test(String tag) { if ("a".equals(tag)) { System.out.println("a"); } else if ("b".equals(tag)) { System.out.println("b"); } System.out.println("當前線程:"+Thread.currentThread().getName()); System.out.println("the end"); } public static void main(String[] args) { // TODO Auto-generated method stub final Synchronized s1 = new Synchronized(); final Synchronized s2 = new Synchronized(); Thread t1 = new Thread(new Runnable(){ @Override public void run() { // TODO Auto-generated method stub s1.test("a"); } },"t1"); Thread t2 = new Thread(new Runnable(){ @Override public void run() { // TODO Auto-generated method stub s2.test("b"); } },"t2"); t1.start(); t2.start(); } }
運行結果
a b 當前線程:t1 the end 當前線程:t2 the end
發如今方法上加上 synchronized關鍵字後 仍是沒有實現一個線程執行時(鎖住代碼),另外的線程等待執行完後再執行的效果。
咱們來看下代碼
t1線程啓動 調用s1.test();方法
這個方法在執行的時候 是看到了test synchronized 關鍵字的 因此方法執行的時候線程會先去嘗試得到對象鎖,這時候 的鎖就是對象s1的鎖,
t2線程啓動 調用s2.test()方法
一樣t2線程在執行到test方法時也看到了 synchronized 關鍵字 因此這時候線程也會去嘗試得到對象鎖 ,
若是這時候,對象鎖被其餘線程得到了 那麼t2線程就進入阻塞 等待狀態 ,
咱們開始會認爲 t2線程走到s2.test()的時候 t1線程已經得到了鎖,因此t2線程這會會阻塞,
但實際上t1線程得到的是 s1的鎖,t2執行到 test方法時 要判斷鎖是否被其餘線程得到,這個鎖是s2的對象鎖,兩個線程得到的鎖是不一樣對象的 因此相互間不影響 ,因此這兩個線程不會等到另一個線程執行完再執行
咱們換一種寫法讓 不一樣的線程調用到test方法時要獲取的對象鎖是同樣的
public class Synchronized { public void test(String tag) { if ("a".equals(tag)) { System.out.println("a"); } else if ("b".equals(tag)) { System.out.println("b"); } System.out.println("當前線程:"+Thread.currentThread().getName()); System.out.println("the end"); } public static void main(String[] args) { // TODO Auto-generated method stub final Synchronized s1 = new Synchronized(); final Synchronized s2 = new Synchronized(); //這裏lock 只是對象的名字 由於功能上比較像鎖 因此就取這名 跟jdk裏面的Lock不要緊 // 後面線程執行的時候都會先獲取到這個對象的鎖 一個線程只有在方法執行完後 纔會把這個對象的鎖釋放掉 final Object lock = new Object(); Thread t1 = new Thread(new Runnable(){ @Override public void run() { synchronized (lock) { // TODO Auto-generated method stub s1.test("a"); } } },"t1"); Thread t2 = new Thread(new Runnable(){ @Override public void run() { synchronized (lock) { // TODO Auto-generated method stub s2.test("b"); } } },"t2"); t1.start(); t2.start(); } }
這時候的運行結果就知足咱們的預期了。
synchronized 修飾 static 方法
方法加上static 後就是類的方法了 不屬於任何對象 這時候在方法上在加上synchronized 修飾 做用的對象是這個類的全部對象,
像前面說的 test 方法 加了 synchronized 修飾後 再加 static 修飾 也能實現 一個線程等待另一個線程執行完的效果