java中的synchronized(同步代碼塊和同步方法的區別)

問題的由來:

看到這樣一個面試題:java

//下列兩個方法有什麼區別
public synchronized void method1(){}

public void method2(){
 synchronized  (obj){}
}

複製代碼

synchronized用於解決同步問題,當有多條線程同時訪問共享數據時,若是不進行同步,就會發生錯誤,java提供的解決方案是:只要將操做共享數據的語句在某一時段讓一個線程執行完,在執行過程當中,其餘線程不能進來執行能夠。解決這個問題。這裏在用synchronized時會有兩種方式,一種是上面的同步方法,即用synchronized來修飾方法,另外一種是提供的同步代碼塊。面試

這裏總感受怪怪的,這兩種方法有什麼區別呢,基礎學得很差,因而就動手作了個簡單的測試,代碼以下:bash

public class SynObj {
	public synchronized void methodA() {
		System.out.println("methodA.....");
		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	public  void methodB() {
	    synchronized(this) {
	        System.out.pritntln("methodB.....");
	    }
	}
	
	public void methodC() {
		String str = "sss";
		synchronized (str) {
			System.out.println("methodC.....");
		}
	}
}
複製代碼
public class TestSyn {
	public static void main(String[] args) {
		final SynObj obj = new SynObj();
		
		Thread t1 = new Thread(new Runnable() {
			@Override
			public void run() {
				obj.methodA();
			}
		});
		t1.start();
		
		Thread t2 = new Thread(new Runnable() {
			@Override
			public void run() {
				obj.methodB();
			}
		});
		t2.start();
		
		Thread t3 = new Thread(new Runnable() {
			@Override
			public void run() {
				obj.methodC();
			}
		});
		t3.start();
	}
}
複製代碼

這段小代碼片斷打印結果以下:ide

methodA.....
methodC.....
//methodB會隔一段時間纔會打印出來
methodB.....
複製代碼

這段代碼的打印結果是,methodA.....methodC.....會很快打印出來,methodB.....會隔一段時間纔打印出來,那麼methodB爲何不能像methodC那樣很快被調用呢?性能

在啓動線程1調用方法A後,接着會讓線程1休眠5秒鐘,這時會調用方法C,注意到方法C這裏用synchronized進行加鎖,這裏鎖的對象是str這個字符串對象。可是方法B則不一樣,是用當前對象this進行加鎖,注意到方法A直接在方法上加synchronized,這個加鎖的對象是什麼呢?顯然,這兩個方法用的是一把鎖。測試

由這樣的結果,咱們就知道這樣同步方法是用什麼加鎖的了,因爲線程1在休眠,這時鎖還沒釋放,致使線程2只有在5秒以後才能調用方法B,由此,可知兩種加鎖機制用的是同一個鎖對象,即當前對象。this

另外,同步方法直接在方法上加synchronized實現加鎖,同步代碼塊則在方法內部加鎖,很明顯,同步方法鎖的範圍比較大,而同步代碼塊範圍要小點,通常同步的範圍越大,性能就越差,通常須要加鎖進行同步的時候,確定是範圍越小越好,這樣性能更好spa

相關文章
相關標籤/搜索