synchronized和lock以及synchronized和volatile的區別


synchronized和volatile區別
synochronizd和volatile關鍵字區別:
1. volatile關鍵字解決的是變量在多個線程之間的可見性;而sychronized關鍵字解決的是多個線程之間訪問共享資源的同步性。
2. volatile只能用於修飾變量,而synchronized可以修飾方法,以及代碼塊。(volatile是線程同步的輕量級實現,所以volatile性能比synchronized要好,並且隨着JDK新版本的發布,sychronized關鍵字在執行上得到很大的提升,在開發中使用synchronized關鍵字的比率還是比較大)
3. 多線程訪問volatile不會發生阻塞,而sychronized會出現阻塞。
4. volatile能保證變量在多個線程之間的可見性,但不能保證原子性;而sychronized可以保證原子性,也可以間接保證可見性,因為它會將私有內存和公有內存中的數據做同步。

線程安全包含原子性和可見性兩個方面。
對於用volatile修飾的變量,JVM虛擬機只是保證從主內存加載到線程工作內存的值是最新的。
一句話說明volatile的作用:實現變量在多個線程之間的可見性。

synchronized和lock區別
1)Lock是一個接口,而synchronized是Java中的關鍵字,synchronized是內置的語言實現;

2)synchronized在發生異常時,會自動釋放線程占有的鎖,因此不會導致死鎖現象發生;而Lock在發生異常時,如果沒有主動通過unLock()去釋放鎖,則很可能造成死鎖現象,因此使用Lock時需要在finally塊中釋放鎖;

3)Lock可以讓等待鎖的線程響應中斷,而synchronized卻不行,使用synchronized時,等待的線程會一直等待下去,不能夠響應中斷;

4)通過Lock可以知道有沒有成功獲取鎖,而synchronized卻無法辦到。

5)Lock可以提高多個線程進行讀操作的效率(讀寫鎖)。

  在性能上來說,如果競爭資源不激烈,兩者的性能是差不多的,而當競爭資源非常激烈時(即有大量線程同時競爭),此時Lock的性能要遠遠優於synchronized。所以說,在具體使用時要根據適當情況選擇。
  

鎖的類型
1.可重入鎖
如果鎖具備可重入性,則稱作為可重入鎖。像synchronized和ReentrantLock都是可重入鎖,可重入性在我看來實際上表明了鎖的分配機制:基於線程的分配,而不是基於方法調用的分配。舉個簡單的例子,當一個線程執行到某個synchronized方法時,比如說method1,而在method1中會調用另外一個synchronized方法method2,此時線程不必重新去申請鎖,而是可以直接執行方法method2。

class MyClass {
    public synchronized void method1() {
        method2();
    }

    public synchronized void method2() {

    }
}

上述代碼中的兩個方法method1和method2都用synchronized修飾了,假如某一時刻,線程A執行到了method1,此時線程A獲取了這個對象的鎖,而由於method2也是synchronized方法,假如synchronized不具備可重入性,此時線程A需要重新申請鎖。但是這就會造成一個問題,因為線程A已經持有了該對象的鎖,而又在申請獲取該對象的鎖,這樣就會線程A一直等待永遠不會獲取到的鎖。

而由於synchronized和Lock都具備可重入性,所以不會發生上述現象。

2.可中斷鎖

可中斷鎖:顧名思義,就是可以相應中斷的鎖。在Java中,synchronized就不是可中斷鎖,而Lock是可中斷鎖。

如果某一線程A正在執行鎖中的代碼,另一線程B正在等待獲取該鎖,可能由於等待時間過長,線程B不想等待了,想先處理其他事情,我們可以讓它中斷自己或者在別的線程中中斷它,這種就是可中斷鎖。lockInterruptibly()方法。

3.公平鎖

公平鎖即盡量以請求鎖的順序來獲取鎖。比如同是有多個線程在等待一個鎖,當這個鎖被釋放時,等待時間最久的線程(最先請求的線程)會獲得該所,這種就是公平鎖。

非公平鎖即無法保證鎖的獲取是按照請求鎖的順序進行的。這樣就可能導致某個或者一些線程永遠獲取不到鎖。

在Java中,synchronized就是非公平鎖,它無法保證等待的線程獲取鎖的順序。
而對於ReentrantLock和ReentrantReadWriteLock,它默認情況下是非公平鎖,但是可以設置為公平鎖。

我們可以在創建ReentrantLock對象時,通過以下方式來設置鎖的公平性:
ReentrantLock lock = new ReentrantLock(true);
如果參數為true表示為公平鎖,為fasle為非公平鎖。默認情況下,如果使用無參構造器,則是非公平鎖。
另外在ReentrantLock類中定義了很多方法,比如:

1   isFair()        //判斷鎖是否是公平鎖
2   isLocked()    //判斷鎖是否被任何線程獲取了
3   isHeldByCurrentThread()   //判斷鎖是否被當前線程獲取了
4   hasQueuedThreads()   //判斷是否有線程在等待該鎖

讀操作不會發生沖突。 
ReadWriteLock就是讀寫鎖,它是一個接口,ReentrantReadWriteLock實現了這個接口。可以通過readLock()獲取讀鎖,通過writeLock()獲取寫鎖。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM