先定义三个Runnable
//读操作
Runnable readTask = () -> {
lock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName() + "获得读锁,开始读操作");
try {
Thread.sleep(3000);
System.out.println(Thread.currentThread().getName() + "读操作完毕");
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName() + "读操作被中断");
}
} finally {
lock.readLock().unlock();
}
};
//写操作
Runnable writeTask = ()->{
lock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName() + "获得写锁,开始写操作");
try {
Thread.sleep(3000);
System.out.println(Thread.currentThread().getName() + "写操作完毕");
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName() + "写操作被中断");
}
}finally {
lock.writeLock().unlock();
}
};
//写+读操作
Runnable writeReadTask = ()->{
lock.writeLock().lock();
try {
System.out.println(Thread.currentThread().getName() + "获得写锁,开始写操作");
lock.readLock().lock();
try {
System.out.println(Thread.currentThread().getName() + "获得写+读锁");
}finally {
lock.readLock().unlock();
}
try {
Thread.sleep(3000);
System.out.println(Thread.currentThread().getName() + "写操作完毕");
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName() + "写操作被中断");
}
}finally {
lock.writeLock().unlock();
}
};
下面开始测试
测试1:
new Thread(readTask, "t1").start();
new Thread(readTask, "t2").start();
Thread.sleep(100);
new Thread(writeTask, "t3").start();
输出 :
测试2:
new Thread(writeTask, "t3").start();
Thread.sleep(100);
new Thread(readTask, "t1").start();
new Thread(readTask, "t2").start();
输出 :
测试3:
new Thread(writeReadTask, "t1").start();
输出 :
总结:
- 读锁是共享的,读过程中,其他线程可以获得读锁,但不能写锁
- 写锁是排它的,写过程中,其他线程不能读写
- 线程获得写锁后,还可以获得读锁
补充: 后面看了ReadLock的源码发现这么个情况
new Thread(readTask, "t1").start();
Thread.sleep(100);
new Thread(writeTask, "t3").start();
Thread.sleep(100);
new Thread(readTask, "t2").start();
输出
t1获得读锁,开始读操作
t1读操作完毕
t3获得写锁,开始写操作
t3写操作完毕
t2获得读锁,开始读操作
t2读操作完毕
想表达的是,当一个线程A获得读锁,然后来一个线程B来请求写锁,这时B会失败入sync队列,接着又来一个线程C请求读锁,这时C也会失败,进入sync队列排在B后面,所以输出就像上面那样了。