java synchronized理解

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


當前線程:t1
the end 

當前線程:t2
the end同步

或者 class


當前線程:t2
the endtest


當前線程: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 修飾 也能實現 一個線程等待另一個線程執行完的效果

相關文章
相關標籤/搜索