本文目錄一覽:
java 鎖有幾種
樂觀鎖/悲觀鎖
樂觀鎖與悲觀鎖不是指具體的什麼類型的鎖,而是指看待並發同步的角度。
悲觀鎖認為對於同一個數據的並發操作,一定是會發生修改的,哪怕沒有修改,也會認為修改。因此對於同一個數據的並發操作,悲觀鎖採取加鎖的形式。悲觀的認為,不加鎖的並發操作一定會出問題。
樂觀鎖則認為對於同一個數據的並發操作,是不會發生修改的。在更新數據的時候,會採用嘗試更新,不斷重新的方式更新數據。樂觀的認為,不加鎖的並發操作是沒有事情的。
從上面的描述我們可以看出,悲觀鎖適合寫操作非常多的場景,樂觀鎖適合讀操作非常多的場景,不加鎖會帶來大量的性能提升。
公平鎖/非公平鎖
公平鎖是指多個線程按照申請鎖的順序來獲取鎖。
非公平鎖是指多個線程獲取鎖的順序並不是按照申請鎖的順序,有可能後申請的線程比先申請的線程優先獲取鎖。
優點:在於吞吐量比公平鎖大。
缺點:可能會造成優先順序反轉或者某些線程飢餓現象(一直拿不到鎖)。
對於Java ReentrantLock而言,通過構造函數指定該鎖是否是公平鎖,默認是非公平鎖。
對於Synchronized而言,也是一種非公平鎖。由於其並不像ReentrantLock是通過AQS的來實現線程調度,所以並沒有任何辦法使其變成公平鎖。
可重入鎖
可重入鎖的概念是自己可以再次獲取自己的內部鎖。
舉個例子,比如一條線程獲得了某個對象的鎖,此時這個對象鎖還沒有釋放,當其再次想要獲取這個對象的鎖的時候還是可以獲取的(如果不可重入的鎖的話,此刻會造成死鎖)。說的更高深一點可重入鎖是一種遞歸無阻塞的同步機制。
對於Java ReentrantLock而言, 他的名字就可以看出是一個可重入鎖,其名字是Re entrant Lock重新進入鎖。
對於Synchronized而言,也是一個可重入鎖。可重入鎖的一個好處是可一定程度避免死鎖。
獨享鎖/共享鎖
獨享鎖是指該鎖一次只能被一個線程所持有。
共享鎖是指該鎖可被多個線程所持有。
對於Java ReentrantLock(互斥鎖)而言,其是獨享鎖。
但是對於Lock的另一個實現類ReadWriteLock(讀寫鎖),其讀鎖是共享鎖,其寫鎖是獨享鎖。讀鎖的共享鎖可保證並發讀是非常高效的,讀寫,寫讀 ,寫寫的過程是互斥的。
對於Synchronized而言,當然是獨享鎖。
分段鎖
分段鎖其實是一種鎖的設計,並不是具體的一種鎖。對於ConcurrentHashMap而言,其並發的實現就是通過分段鎖的形式來實現高效的並發操作。
我們以ConcurrentHashMap來說一下分段鎖的含義以及設計思想,ConcurrentHashMap中的分段鎖稱為Segment,它即類似於HashMap(JDK7與JDK8中HashMap的實現)的結構,即內部擁有一個Entry數組,數組中的每個元素又是一個鏈表;同時又是一個ReentrantLock(Segment繼承了ReentrantLock)。
當需要put元素的時候,並不是對整個hashmap進行加鎖,而是先通過hashcode來知道他要放在那一個分段中,然後對這個分段進行加鎖,所以當多線程put的時候,只要不是放在一個分段中,就實現了真正的並行的插入。
但是,在統計size的時候,可就是獲取hashmap全局信息的時候,就需要獲取所有的分段鎖才能統計。
分段鎖的設計目的是細化鎖的粒度,當操作不需要更新整個數組的時候,就僅僅針對數組中的一項進行加鎖操作。
互斥鎖:
無法獲取瑣時,進線程立刻放棄剩餘的時間片並進入阻塞(或者說掛起)狀態,同時保存寄存器和程序計數器的內容(保存現場,上下文切換的前半部分),當可以獲取鎖時,進線程激活,等待被調度進CPU並恢復現場(上下文切換下半部分)
上下文切換會帶來數十微秒的開銷,不要在性能敏感的地方用互斥鎖
讀寫鎖:
1)多個讀者可以同時進行讀
2)寫者必須互斥(只允許一個寫者寫,也不能讀者寫者同時進行)
3)寫者優先於讀者(一旦有寫者,則後續讀者必須等待,喚醒時優先考慮寫者)
自旋鎖:
自旋鎖是指嘗試獲取鎖的線程不會立即阻塞,而是採用循環的方式去嘗試獲取鎖,這樣的好處是減少線程上下文切換的消耗,缺點是循環會消耗CPU。
如何使用java的鎖機制
可以在臨界區代碼開始的位置執行Lock類的lock方法,為代碼塊加鎖,而在臨界區的出口使用相同Lock實例的unlock方法,釋放臨界區資源。
Demo2-12中,主線程先創建了一個lockTest對象test,然後將相同的test對象交給兩個不同的線程執行。子線程1獲取到了lock後,開始執行before sleep輸出語句,遇到sleep後,線程1阻塞將會放棄執行權,這時線程2可以獲取執行權,當線程2執行lock方法時,發現鎖已經被別的線程獲取,所以線程2阻塞等待lock的釋放。線程1從sleep中被喚醒後,將繼續執行after sleep語句,之後釋放了鎖,此時線程2從鎖等待中被喚醒,執行臨近區的內容,因此Demo2-12的輸出是先線程1的兩條語句,之後才輸出線程2的兩條語句。而Demo2-13在沒有鎖的保護下,程序無法保證先將線程1的兩條語句輸出後再執行線程2的輸出,因此,Demo2-13的輸出結果是交叉的。
在java中有哪些鎖
給你整理了Java中的一些鎖:
公平鎖/非公平鎖
可重入鎖
獨享鎖/共享鎖
互斥鎖/讀寫鎖
樂觀鎖/悲觀鎖
分段鎖
偏向鎖/輕量級鎖/重量級鎖
自旋鎖
上面是很多鎖的名詞,這些分類並不是全是指鎖的狀態,有的指鎖的特性,有的指鎖的設計
java中悲觀鎖和樂觀鎖的區別
樂觀鎖和悲觀鎖的區別如下:
1、悲觀鎖是當線程拿到資源時,就對資源上鎖,並在提交後,才釋放鎖資源,其他線程才能使用資源。
2、樂觀鎖是當線程拿到資源時,上樂觀鎖,在提交之前,其他的鎖也可以操作這個資源,當有衝突的時候,並發機制會保留前一個提交,打回後一個提交,讓後一個線程重新獲取資源後,再操作,然後提交。和git上傳代碼一樣,兩個線程都不是直接獲取資源本身,而是先獲取資源的兩個copy版本,然後在這兩個copy版本上修改。
3、悲觀鎖和樂觀鎖在並發量低的時候,性能差不多,但是在並發量高的時候,樂觀鎖的性能遠遠優於悲觀鎖。
4、常用的synchronized是悲觀鎖,lock是樂觀鎖。
原創文章,作者:ROFI,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/141168.html
微信掃一掃
支付寶掃一掃