ReentrantReadWriteLock
ReentrantReadWriteLock:读写锁,一个是读操作相关的锁,称为共享锁;另一个是写操作相关的锁,也叫排他锁。也就是多个读锁之间不互斥,读锁与写锁互斥,写锁与写锁互斥。由于ReentrantLock具有完全互斥排他的效果,也就是同一时间只有一个线程在执行ReentrantLock.lock()方法后面的任务。虽然保证了实例变量的安全性,但是效率非常低下,所以JDK中提供了这种读写锁,使用它可以加快运行效率。举例如下:
1.读读共享
//读读共享
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 static void main(String[] args) {
Service service = new Service();
ThreadA threadA = new ThreadA(service);
threadA.setName("A");
ThreadB threadB = new ThreadB(service);
threadB.setName("B");
threadA.start();
threadB.start();
}
}
public class ThreadA extends Thread{
private Service service;
public ThreadA(Service service) {
super();
this.service = service;
}
@Override
public void run() {
service.read();
}
}
public class ThreadB extends Thread{
private Service service;
public ThreadB(Service service) {
super();
this.service = service;
}
@Override
public void run() {
service.read();
}
}
运行结果:
获得读锁 A 1525617940582
获得读锁 B 1525617940582
分析:从时间来看,两个线程几乎同时进入lock()方法后面的代码。说明在此使用lock.readLock()读锁可以提高程序运行的效率,允许多个线程同时执行lock();
2.读写互斥
//读写互斥
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();
}
}
注:ThreadB中:
@Override
public void run() {
service.write();
}
运行结果:
获得读锁 A 1525618079549
获得写锁 B 1525618089551
分析:说明“读写”操作是互斥的。
3.写写互斥
public class Service {
private ReentrantReadWriteLock lock=
new ReentrantReadWriteLock();
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();
ThreadB b = new ThreadB(service);
b.setName("B");
b.start();
ThreadB b2 = new ThreadB(service);
b2.setName("B2");
b2.start();
}
}
运行结果:
获得写锁 B 1525618508073
获得写锁 B2 1525618518076
分析:说明同一时间只允许一个线程执行lock()方法后面的代码。
4.写读互斥
public class Service {
private ReentrantReadWriteLock lock=
new ReentrantReadWriteLock();
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 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 static void main(String[] args) throws InterruptedException {
// 写读互斥
Service service = new Service();
ThreadB b = new ThreadB(service);
b.setName("B");
b.start();
ThreadA a = new ThreadA(service);
a.setName("A");
a.start();
}
}
运行结果:
获得写锁 B 1525618801176
获得读锁 A 1525618811178
分析:说明“写读”操作也是互斥的。
5原理分析