4.2 ReentrantReadWriteLock
读写锁包括共享锁(读)、排他锁(写)。
没有线程进行写入操作时,多个读取线程都可以获得锁,而进行写入操作的线程只有获得写入锁才能写入。
- 读读共享
- 写写互斥
- 读写互斥
- 写读互斥
Service.java
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class Service {
private ReentrantReadWriteLock lock;
public Service(ReentrantReadWriteLock lock){
this.lock = lock;
}
public void read(){
lock.readLock().lock();
System.out.println(Thread.currentThread().getName() + " " +System.currentTimeMillis());
lock.readLock().unlock();
}
}
ThreadA.java
public class ThreadA extends Thread{
private Service service;
public ThreadA(Service service){
this.service = service;
}
@Override
public void run(){
service.read();
}
}
ThreadB.java
public class ThreadB extends Thread{
private Service service;
public ThreadB(Service service){
this.service = service;
}
@Override
public void run(){
service.read();
}
}
Run.java
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class Run {
public static void main(String[] args) {
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
Service service = new Service(lock);
ThreadA A = new ThreadA(service);
ThreadB B = new ThreadB(service);
A.start();
B.start();
}
}
执行结果
Thread-0 1632923125926
Thread-1 1632923125926
两个线程打印的间隔时间很短,几乎同时访问共享锁锁住的内容,这样的共享锁可以提高程序的运行效率。
把读锁换成写锁 lock.writeLock.lock(),则 A B两个线程执行 service.read() 进行的是写锁(排他锁)。
运行结果:
Thread-0 1632923636440
Thread-1 1632923636451
可以发现两个线程打印的间隔较长(单位毫秒)。
Service.java
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class Service {
private ReentrantReadWriteLock lock;
public Service(ReentrantReadWriteLock lock){
this.lock = lock;
}
public void read(){
try{
lock.readLock().lock();
System.out.println("read:" + Thread.currentThread().getName() + " " +System.currentTimeMillis());
Thread.sleep(3000);
}catch (InterruptedException e){
}finally {
lock.readLock().unlock();
}
}
public void write(){
try {
lock.writeLock().lock();
System.out.println("write:"+ Thread.currentThread().getName() + " " +System.currentTimeMillis());
Thread.sleep(3000);
}catch (InterruptedException e){
}finally {
lock.writeLock().unlock();
}
}
}
ThreadA.java
public class ThreadA extends Thread{
private Service service;
public ThreadA(Service service){
this.service = service;
}
@Override
public void run(){
service.read();
}
}
ThreadB.java
public class ThreadB extends Thread{
private Service service;
public ThreadB(Service service){
this.service = service;
}
@Override
public void run(){
service.write();
}
}
Run.java
public class Run {
public static void main(String[] args) throws InterruptedException {
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
Service service = new Service(lock);
ThreadA A = new ThreadA(service);
ThreadB B = new ThreadB(service);
A.start();
Thread.sleep(1000);
B.start();
}
}
运行结果:
read:Thread-0 1632924236688
write:Thread-1 1632924239709
线程 A 在读取时,线程 B 想要写入,二者之间是互斥的。
将 Run.java 中的 线程 A 和线程 B 的执行顺序颠倒,也会产生互斥。
A.start();
Thread.sleep(1000);
B.start();