日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

谈谈java并发锁(重入锁、读写锁、公平锁)

發(fā)布時(shí)間:2025/3/19 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 谈谈java并发锁(重入锁、读写锁、公平锁) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

目錄

重入鎖

簡(jiǎn)單重入鎖

重入鎖的等待通知(Condition)

多Condition

公平鎖和非公平鎖

讀寫鎖ReentrantReadWriteLock

鎖優(yōu)化總結(jié):


重入鎖和讀寫鎖,他們具有比synchronized更為強(qiáng)大的功能,并且有嗅探鎖定、多路分支等功能。

重入鎖

在需要進(jìn)行同步的代碼部分加上鎖定,但不要忘記最后一定要釋放鎖定,不然會(huì)造成鎖永遠(yuǎn)無(wú)法釋放,其他線程永遠(yuǎn)進(jìn)不來(lái)的結(jié)果。

簡(jiǎn)單重入鎖

//一定要在finally中解鎖 //感覺跟synchronized沒啥區(qū)別,是對(duì)象鎖。也許性能比較好一些 public class UseReentrantLock {//private Lock lock = new ReentrantLock();//定義一個(gè)鎖沖突public void method1(){Lock lock = new ReentrantLock();//定義兩個(gè)鎖不沖突try {lock.lock();System.out.println("當(dāng)前線程:" + Thread.currentThread().getName() + "進(jìn)入method1..");Thread.sleep(1000);System.out.println("當(dāng)前線程:" + Thread.currentThread().getName() + "退出method1..");Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}}public void method2(){Lock lock = new ReentrantLock();//定義兩個(gè)鎖不沖突try {lock.lock();System.out.println("當(dāng)前線程:" + Thread.currentThread().getName() + "進(jìn)入method2..");Thread.sleep(2000);System.out.println("當(dāng)前線程:" + Thread.currentThread().getName() + "退出method2..");Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}}public static void main(String[] args) {final UseReentrantLock ur = new UseReentrantLock();final UseReentrantLock ur2 = new UseReentrantLock();Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {ur.method1();}}, "t1");Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {ur2.method2();}}, "t2");t1.start();t2.start();try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}//System.out.println(ur.lock.getQueueLength());} }

重入鎖的等待通知(Condition)

就像synchronized,wait()、notify()、notifyAll()。

同樣,在使用Lock的時(shí)候,可以使用一個(gè)新的等待/通知的類,它就是Condition。這個(gè)Condition一定是針對(duì)具體某一把鎖的。也就是在只有鎖的基礎(chǔ)之上才會(huì)產(chǎn)生Condition。

public class UseCondition {private Lock lock = new ReentrantLock();private Condition condition = lock.newCondition();public void method1(){try {lock.lock();System.out.println("當(dāng)前線程:" + Thread.currentThread().getName() + "進(jìn)入等待狀態(tài)..");Thread.sleep(3000);System.out.println("當(dāng)前線程:" + Thread.currentThread().getName() + "釋放鎖..");condition.await(); // Object waitSystem.out.println("當(dāng)前線程:" + Thread.currentThread().getName() +"繼續(xù)執(zhí)行...");} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}public void method2(){try {lock.lock();System.out.println("當(dāng)前線程:" + Thread.currentThread().getName() + "進(jìn)入..");Thread.sleep(3000);System.out.println("當(dāng)前線程:" + Thread.currentThread().getName() + "發(fā)出喚醒..");condition.signal(); //Object有notifyAll,同理這里也有signalAll()方法} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}public static void main(String[] args) {final UseCondition uc = new UseCondition();Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {uc.method1();}}, "t1");Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {uc.method2();}}, "t2");t1.start();t2.start();} }

多Condition

我們可以通過一個(gè)Lock對(duì)象產(chǎn)生多個(gè)Condition進(jìn)行多線程間的交互,非常的靈活。可以使得部分需要喚醒的線程喚醒,其他線程則繼續(xù)等待通知。

//兩個(gè)Condition是獨(dú)立的!!! public class UseManyCondition {private ReentrantLock lock = new ReentrantLock();private Condition c1 = lock.newCondition();private Condition c2 = lock.newCondition();public void m1(){try {lock.lock();System.out.println("當(dāng)前線程:" +Thread.currentThread().getName() + "進(jìn)入方法m1等待..");c1.await();System.out.println("當(dāng)前線程:" +Thread.currentThread().getName() + "方法m1繼續(xù)..");} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}public void m2(){try {lock.lock();System.out.println("當(dāng)前線程:" +Thread.currentThread().getName() + "進(jìn)入方法m2等待..");c1.await();System.out.println("當(dāng)前線程:" +Thread.currentThread().getName() + "方法m2繼續(xù)..");} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}public void m3(){try {lock.lock();System.out.println("當(dāng)前線程:" +Thread.currentThread().getName() + "進(jìn)入方法m3等待..");c2.await();System.out.println("當(dāng)前線程:" +Thread.currentThread().getName() + "方法m3繼續(xù)..");} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}public void m4(){try {lock.lock();System.out.println("當(dāng)前線程:" +Thread.currentThread().getName() + "喚醒..");c1.signalAll();} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}public void m5(){try {lock.lock();System.out.println("當(dāng)前線程:" +Thread.currentThread().getName() + "喚醒..");c2.signal();} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}public static void main(String[] args) {final UseManyCondition umc = new UseManyCondition();Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {umc.m1();}},"t1");Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {umc.m2();}},"t2");Thread t3 = new Thread(new Runnable() {@Overridepublic void run() {umc.m3();}},"t3");Thread t4 = new Thread(new Runnable() {@Overridepublic void run() {umc.m4();}},"t4");Thread t5 = new Thread(new Runnable() {@Overridepublic void run() {umc.m5();}},"t5");t1.start(); // c1t2.start(); // c1t3.start(); // c2try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}t4.start(); // c1try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}t5.start(); // c2} }

公平鎖和非公平鎖

默認(rèn)是非公平,非公平鎖效率比較高。

Lock?lock = new ReentrantLock(boolean isFair);//可傳參,默認(rèn)是false非公平鎖。

lock用法:

tryLock():嘗試獲得鎖,獲得結(jié)果用true/false返回。

tryLock():在給定的時(shí)間內(nèi)嘗試獲得鎖,獲得結(jié)果用true/false返回。

isFair():是否是公平鎖。

isLocked():是否鎖定。

getHoldCount():查詢當(dāng)前線程保持此鎖的個(gè)數(shù),也就是調(diào)用lock()次數(shù)。

lockInterruptibly():優(yōu)先響應(yīng)中斷的鎖。

getQueueLength():返回正在等待獲取此鎖的線程數(shù)。

getWaitQueueLength():返回等待與鎖定相關(guān)的給定條件Condition的線程數(shù)。

hasQueuedThread(Thread thread):查詢指定的線程是否在等待此鎖。

hasQueuedThreads():查詢是否有線程正在等待此鎖。

hasWaiters():查詢是否有線程正在等待與此鎖定有關(guān)的condition條件。

讀寫鎖ReentrantReadWriteLock

讀寫鎖ReentrantReadWriteLock,其核心就是實(shí)現(xiàn)讀寫分離的鎖。在高并發(fā)訪問下,尤其是讀多寫少的情況下,性能要遠(yuǎn)高于重入鎖。

之前的synchronized、ReentrantLock,我們知道,同一時(shí)間內(nèi)只能有一個(gè)線程進(jìn)行訪問被鎖定的代碼,那么讀寫鎖則不同,其本質(zhì)是分成兩個(gè)鎖,即讀鎖、寫鎖。在讀鎖下,多個(gè)線程可以并發(fā)的進(jìn)行訪問,但是在寫鎖的時(shí)候,只能一個(gè)個(gè)的順序訪問。

口訣:讀讀共享,寫寫互斥,讀寫互斥

public class UseReentrantReadWriteLock {private ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();private ReadLock readLock = rwLock.readLock();private WriteLock writeLock = rwLock.writeLock();public void read(){try {readLock.lock();System.out.println("當(dāng)前線程:" + Thread.currentThread().getName() + "進(jìn)入...");Thread.sleep(3000);System.out.println("當(dāng)前線程:" + Thread.currentThread().getName() + "退出...");} catch (Exception e) {e.printStackTrace();} finally {readLock.unlock();}}public void write(){try {writeLock.lock();System.out.println("當(dāng)前線程:" + Thread.currentThread().getName() + "進(jìn)入...");Thread.sleep(3000);System.out.println("當(dāng)前線程:" + Thread.currentThread().getName() + "退出...");} catch (Exception e) {e.printStackTrace();} finally {writeLock.unlock();}}public static void main(String[] args) {final UseReentrantReadWriteLock urrw = new UseReentrantReadWriteLock();Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {urrw.read();}}, "t1");Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {urrw.read();}}, "t2");Thread t3 = new Thread(new Runnable() {@Overridepublic void run() {urrw.write();}}, "t3");Thread t4 = new Thread(new Runnable() {@Overridepublic void run() {urrw.write();}}, "t4"); // t1.start();// R // t2.start();// R// t1.start(); // R // t3.start(); // Wt3.start();// Wt4.start();// W} }

鎖優(yōu)化總結(jié):

1.避免死鎖。

2.減小鎖的持有時(shí)間。

3.減小鎖的粒度。

4.鎖的分離(讀寫鎖)。

5.盡量使用無(wú)鎖的操作,如原子操作(Atomic系列類),volatile關(guān)鍵字。

總結(jié)

以上是生活随笔為你收集整理的谈谈java并发锁(重入锁、读写锁、公平锁)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。