ReentrantReadWriteLock的使用:
- 读读共享: 写写互斥: 读写互斥: 写读互斥:
类ReentrantLock具有完全互斥排他的效果,即同一时间只有一个线程在执行ReentrantLock.lock()方法后面得任务。
这样做虽然保证了实例变量得线程安全性,但效率却是非常底下得,所以在JDK中提供了一种读写锁ReentrantReadWriteLock类,使用它可以加快运行效率,在某些不需要操作实例变量得方法中,完全可以使用读写锁ReentrantReadWriteLock来提升该方法的代码运行速度。
读写锁表示也有两个锁,一个是读写操作相关的锁,也称为共享锁;另一个是写操作相关的锁,也叫排他锁。也就是多个读锁之间不互斥,读锁与写锁互斥,写锁与写锁互斥。
在没有线程Thread进行写入操作时,进行读取操作的多个Thread都可以获取读锁,而进行写入操作的Thread只有在读取写锁后才能进行写入操作。
即多个Thread可以同时进行读取操作,但是同一时刻只允许一个Thread进行写入操作。
读读共享:
从运行结果上看,两个线程几乎同时进去lock()方法后面的代码。说明使用lock.readLock()读锁可以提高程序运行效率,允许多个线程同时执行lock()方法后面的代码。
写写互斥:
修改Service中的read()方法:
lock.writeLock():同一时间只允许一个线程执行lock()方法后面的代码。
读写互斥:
public class Service {
private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
public void read() {
try {
try {
lock.readLock().lock();
System.out.println("获取读锁" + Thread.currentThread().getName()
+ " " +System.currentTimeMillis());
Thread.sleep(10000);
} finally {
lock.readLock().unlock();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void write() {
try {
try {
lock.writeLock().lock();
System.out.println("获取写锁" + Thread.currentThread().getName()
+ " " +System.currentTimeMillis());
Thread.sleep(10000);
} finally {
lock.writeLock().unlock();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args)throws InterruptedException {
Service service = new Service();
ThreadA a = new ThreadA(service);
a.setName("A");
a.start();
Thread.sleep(1000);
ThreadB b = new ThreadB(service);
b.setName("B");
b.start();
}
}
写读互斥:
修改main方法():
读写,写读,写写都是互斥的,读读是异步的,非互斥的。