JUC提供了專門的讀寫鎖ReadWriteLock,可以分別用于對讀操作或者寫操作進(jìn)行加鎖蕾久,在源碼中主要定義了兩個接口,分別是readLock和writeLock:
readLock 讀鎖
加了讀鎖的資源窜骄,可以在沒有寫鎖的時候被多個線程共享屁药,換句話說征峦,如果線程1獲取了讀鎖,那么此時可能存在兩種狀態(tài):
- 如果2線程要申請寫鎖呆贿,則2線程會一直等待1線程釋放讀鎖
- 如果2線程要申請讀鎖嚷兔,則2線程可以直接讀取資源,也就是說讀鎖是共享鎖
writeLock 寫鎖
寫鎖是獨占鎖做入,加了寫鎖的資源谴垫,不能再被其他線程讀或者寫,如果1線程已經(jīng)獲取了寫鎖母蛛,那么無論2線程要申請寫鎖或者讀鎖翩剪,都必須等待1線程釋放寫鎖
第一種情況,當(dāng)1線程獲取了讀鎖后彩郊,2線程也可以獲取讀鎖
/**
* 第一種情況前弯,當(dāng)1線程獲取了讀鎖后,2線程也可以獲取讀鎖
*/
//讀寫鎖的實現(xiàn)類
ReentrantReadWriteLock reentrantReadWriteLock=new ReentrantReadWriteLock();
new Thread(()->{
reentrantReadWriteLock.readLock().lock();
for(int i=0;i<100000;i++){
System.out.println(Thread.currentThread().getName()+"正在進(jìn)行讀操作");
}
System.out.println(Thread.currentThread().getName()+"讀操作完畢");
reentrantReadWriteLock.readLock().unlock();
}).start();
new Thread(()->{
reentrantReadWriteLock.readLock().lock();
for(int i=0;i<100000;i++){
System.out.println(Thread.currentThread().getName()+"正在進(jìn)行讀操作");
}
System.out.println(Thread.currentThread().getName()+"讀操作完畢");
reentrantReadWriteLock.readLock().unlock();
}).start();
運行截圖:
image-20210624100526881.png
可以看到線程1和線程2交替執(zhí)行
第二種情況 當(dāng)線程1獲取了讀鎖后秫逝,線程2獲取寫鎖
//讀寫鎖的實現(xiàn)類
ReentrantReadWriteLock reentrantReadWriteLock=new ReentrantReadWriteLock();
new Thread(()->{
reentrantReadWriteLock.readLock().lock();
for(int i=0;i<100000;i++){
System.out.println(Thread.currentThread().getName()+"正在進(jìn)行讀操作");
}
System.out.println(Thread.currentThread().getName()+"讀操作完畢");
reentrantReadWriteLock.readLock().unlock();
}).start();
new Thread(()->{
reentrantReadWriteLock.writeLock().lock();
for(int i=0;i<100000;i++){
System.out.println(Thread.currentThread().getName()+"正在進(jìn)行寫操作");
}
System.out.println(Thread.currentThread().getName()+"寫操作完畢");
reentrantReadWriteLock.writeLock().unlock();
}).start();
運行截圖:
image-20210624100830746.png
線程1獲取了讀鎖恕出,線程2嘗試獲取寫鎖,需要等線程1釋放讀鎖后
第三種情況 當(dāng)線程1獲取了寫鎖违帆,線程2獲取寫鎖或者讀鎖讀都需要等待線程1釋放寫鎖
/**
* 第三種情況浙巫,當(dāng)線程1先獲取寫鎖,不管線程2獲取讀鎖還是寫鎖都要先等線程1釋放寫鎖
*/
//讀寫鎖的實現(xiàn)類
ReentrantReadWriteLock reentrantReadWriteLock=new ReentrantReadWriteLock();
new Thread(()->{
reentrantReadWriteLock.writeLock().lock();
for(int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+"正在進(jìn)行寫操作");
}
System.out.println(Thread.currentThread().getName()+"寫操作完畢");
reentrantReadWriteLock.writeLock().unlock();
}).start();
new Thread(()->{
reentrantReadWriteLock.readLock().lock();
for(int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+"正在進(jìn)行讀操作");
}
System.out.println(Thread.currentThread().getName()+"讀操作完畢");
reentrantReadWriteLock.readLock().unlock();
}).start();
運行截圖:
image-20210624101225906.png