天天看點

Synchronized關鍵字、Lock之間的差別

Synchronized關鍵字、Lock之間的差別

  • ReentrantLock擁有與Synchronized相同的并發性和記憶體語義,但是其還多了鎖投票、定時鎖等候和中斷鎖等候

    例如: 線程A和B都要擷取對象O的鎖定,假設A擷取了對象O鎖,B将等待A釋放對O的鎖定,如果使用 synchronized ,如果A不釋放,B将一直等下去,不能被中斷如果 使用ReentrantLock,如果A不釋放,可以使B在等待了足夠長的時間以後,中斷等待,而幹别的事情

ReentrantLock擷取鎖定的三種方式:

1. Lock(),如果擷取了鎖立即傳回,如果别的線程持有鎖,目前線程則一直處于休眠狀态,直到擷取鎖;
2. tryLock(),如果擷取了鎖立即傳回true,如果别的線程正持有鎖,立即傳回false;
3. tryLock(long timeout,TimeUnit unit),如果擷取了鎖立即傳回true,如果别的線程正持有鎖,會等待給定參數的時間,在等待過程中,如果擷取了鎖,就傳回true,如果等待逾時,傳回false;
lockInterruptibly():如果擷取了鎖定立即傳回,如果沒有擷取鎖定,目前線程處于休眠狀态,直到獲得鎖定,或者目前線程被别的線程中斷
           
  • synchronized是在JVM層面上實作的,不但可以通過一些監控工具監控synchronized的鎖定,而且在代碼執行時出現異常,JVM會釋放鎖定,但是使用Lock不行,lock是通過代碼實作的,要保證鎖定一定會被釋放,就必須将unlock()放到finally{}中
  • 在資源競争不是很激烈的情況下,Synchronized的性能要優于ReetrantLock,但是在資源競争很激烈的情況下,Synchronized的性能會下降幾十倍,但是ReetrantLock的性能能維持常态;

    5.0的多線程任務包對于同步的性能方面有了很大的改進,在原有synchronized關鍵字的基礎上,又增加了ReentrantLock,以及各種Atomic類。了解其性能的優劣程度,有助與我們在特定的情形下做出正确的選擇。

總體的結論先擺出來:

**synchronized: **

在資源競争不是很激烈的情況下,偶爾會有同步的情形下,synchronized是很合适的。原因在于,編譯程式通常會盡可能的進行優化synchronize,另外可讀性非常好,不管用沒用過5.0多線程包的程式員都能了解。

ReentrantLock:

ReentrantLock提供了多樣化的同步,比如有時間限制的同步,可以被Interrupt的同步(synchronized的同步是不能Interrupt的)等。在資源競争不激烈的情形下,性能稍微比synchronized差點點。但是當同步非常激烈的時候,synchronized的性能一下子能下降好幾十倍。而ReentrantLock确還能維持常态。

**Atomic: **

和上面的類似,不激烈情況下,性能比synchronized略遜,而激烈的時候,也能維持常态。激烈的時候,Atomic的性能會優于ReentrantLock一倍左右。但是其有一個缺點,就是隻能同步一個值,一段代碼中隻能出現一個Atomic的變量,多于一個同步無效。因為他不能在多個Atomic之間同步。

是以:

我們寫同步的時候,優先考慮synchronized,如果有特殊需要,再進一步優化。ReentrantLock和Atomic如果用的不好,不僅不能提高性能,還可能帶來災難。

ReentrantLock适用場景

1. 某個線程在等待一個鎖的控制權的這段時間需要中斷;
2. 需要分開處理一些wait-notify,ReentrantLock裡面的Condition應用,能夠控制notify哪個線程,鎖可以綁定多個條件.
3. 具有公平鎖功能,每個到來的線程都将排隊等候.