特性:寫寫互斥、讀寫互斥、讀讀共享
鎖降級:寫線程擷取寫入鎖後可以擷取讀取鎖,然後釋放寫入鎖,這樣就從寫入鎖變成了讀取鎖,進而實作鎖降級的特性
public class ReentrantReadWriteLockDemo {
private int i = 0;
private int j = 0;
// 擷取鎖
private ReadWriteLock lock = new ReentrantReadWriteLock();
Lock readLock = lock.readLock();
Lock writeLock = lock.writeLock();
// 使用讀鎖
public void out(){
readLock.lock();
try {
System.out.println(Thread.currentThread().getName()+"i的值====》"+i + "j的值====》"+j);
}finally {
readLock.unlock();
}
}
// 使用寫鎖
public void inCreate() {
writeLock.lock();
try {
i++;
Thread.sleep(500L);
j++;
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
writeLock.unlock();
}
}
// 測試
public static void main(String[] args) {
ReentrantReadWriteLockDemo reentrantReadWriteLockDemo = new ReentrantReadWriteLockDemo();
// 測試1,3個線程,先寫後讀
for (int i = 0; i < 3; i++) {
new Thread(()->{
reentrantReadWriteLockDemo.inCreate();
reentrantReadWriteLockDemo.out();
}).start();
}
}
}
# 控制台結果:
Thread-2i的值====》3j的值====》3
Thread-1i的值====》3j的值====》3
Thread-0i的值====》3j的值====》3
- debug調試
鎖(五):讀寫鎖 - 線程0拿到寫鎖,釋放寫鎖
鎖(五):讀寫鎖 - 執行完畢
鎖(五):讀寫鎖 - 之後執行線程1和線程2
- 案例2
public class ReentrantReadWriteLockDemo {
private int i = 0;
private int j = 0;
// 擷取鎖
private ReadWriteLock lock = new ReentrantReadWriteLock();
Lock readLock = lock.readLock();
Lock writeLock = lock.writeLock();
// 使用讀鎖
public void out(){
readLock.lock();
try {
System.out.println(Thread.currentThread().getName()+"i的值====》"+i + "j的值====》"+j);
}finally {
readLock.unlock();
}
}
// 使用寫鎖
public void inCreate() {
writeLock.lock();
try {
i++;
Thread.sleep(500L);
j++;
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
writeLock.unlock();
}
}
// 測試
public static void main(String[] args) {
ReentrantReadWriteLockDemo reentrantReadWriteLockDemo = new ReentrantReadWriteLockDemo();
// 測試2,2個線程,先讀後寫
new Thread(()->{
reentrantReadWriteLockDemo.out();
},"讀線程").start();
new Thread(()->{
reentrantReadWriteLockDemo.inCreate();
},"寫線程").start();
}
}
- debug調試
鎖(五):讀寫鎖 - 如下:讀線程擷取到鎖,但還沒有釋放
鎖(五):讀寫鎖 - 切換到寫線程,下一步時報錯如下,說明讀寫是互斥的
鎖(五):讀寫鎖 - 案例3
public class ReentrantReadWriteLockDemo {
private int i = 0;
private int j = 0;
// 擷取鎖
private ReadWriteLock lock = new ReentrantReadWriteLock();
Lock readLock = lock.readLock();
Lock writeLock = lock.writeLock();
// 使用讀鎖
public void out(){
readLock.lock();
try {
System.out.println(Thread.currentThread().getName()+"i的值====》"+i + "j的值====》"+j);
}finally {
readLock.unlock();
}
}
// 使用寫鎖
public void inCreate() {
writeLock.lock();
try {
i++;
Thread.sleep(500L);
j++;
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
writeLock.unlock();
}
}
// 測試
public static void main(String[] args) {
ReentrantReadWriteLockDemo reentrantReadWriteLockDemo = new ReentrantReadWriteLockDemo();
// 測試3,2個線程,讀讀操作
new Thread(()->{
reentrantReadWriteLockDemo.out();
},"讀線程1").start();
new Thread(()->{
reentrantReadWriteLockDemo.out();
},"讀線程2").start();
}
}
- debug調試
- 首先讀線程1擷取到鎖,但還沒有釋放
鎖(五):讀寫鎖 - 切換到讀線程2,下一步,可以擷取到鎖,說明讀讀是共享的