ReentrantReadWriteLock
ReentrantLock具有互斥排他的效果,即同一时间只有一个线程在执行ReentrantLock.lock()方法后面的任务。(这种做法虽然保证了变量的线程安全性,但效率非常低下)
ReentrantReadWriteLock也叫读写锁,一个是读操作相关的锁,也称为共享锁;另一个是写操作相关的锁,也叫排他锁。(多个读锁之间不互斥,读锁与写锁互斥,写锁与写锁互斥)
读读共享
/**
* @author 作者 E-mail:
* 类说明
*/
//结果是读锁跟读锁是不需要等待,是共享的。
public class ReetrantReadRead {
public static void main(String[] args) {
Service service=new Service();
ThreadA threadA=new ThreadA(service);
ThreadB threadB=new ThreadB(service);
new Thread(threadA).start();
new Thread(threadB).start();
}
}
class Service{
private ReentrantReadWriteLock lock=new ReentrantReadWriteLock();
public void read(){
lock.readLock().lock();
System.out.println("获得读锁:"+Thread.currentThread().getName()+":"+new Date());
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
System.out.println("取消读锁:"+Thread.currentThread().getName()+":"+new Date());
lock.readLock().unlock();
}
}
}
class ThreadA implements Runnable{
private Service service;
public ThreadA(Service service) {
this.service=service;
}
@Override
public void run() {
service.read();
}
}
class ThreadB implements Runnable{
private Service service;
public ThreadB(Service service) {
this.service=service;
}
@Override
public void run() {
service.read();
}
}
结果:
获得读锁:Thread-1:Sun Oct 28 18:43:16 CST 2018
获得读锁:Thread-0:Sun Oct 28 18:43:16 CST 2018
取消读锁:Thread-0:Sun Oct 28 18:43:27 CST 2018
取消读锁:Thread-1:Sun Oct 28 18:43:27 CST 2018
读写互斥
/**
* @author 作者 E-mail:
* 类说明
*/
//结果读写锁操作是互斥的,写读亦是一样
public class ReetrantReadRead {
public static void main(String[] args) {
Service service=new Service();
ThreadA threadA=new ThreadA(service);
ThreadB threadB=new ThreadB(service);
//读写
new Thread(threadA).start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
new Thread(threadB).start();
//写读
// new Thread(threadB).start();
// try {
// Thread.sleep(500);
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// new Thread(threadA).start();
}
}
class Service{
private ReentrantReadWriteLock lock=new ReentrantReadWriteLock();
public void read(){
lock.readLock().lock();
System.out.println("获得读锁:"+Thread.currentThread().getName()+":"+new Date());
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
System.out.println("取消读锁:"+Thread.currentThread().getName()+":"+new Date());
lock.readLock().unlock();
}
}
public void write(){
lock.writeLock().lock();
System.out.println("获得写锁:"+Thread.currentThread().getName()+":"+new Date());
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
System.out.println("取消写锁:"+Thread.currentThread().getName()+":"+new Date());
lock.writeLock().unlock();
}
}
}
class ThreadA implements Runnable{
private Service service;
public ThreadA(Service service) {
this.service=service;
}
@Override
public void run() {
service.read();
}
}
class ThreadB implements Runnable{
private Service service;
public ThreadB(Service service) {
this.service=service;
}
@Override
public void run() {
service.write();
}
}
读写结果:
获得读锁:Thread-0:Sun Oct 28 18:50:24 CST 2018
取消读锁:Thread-0:Sun Oct 28 18:50:34 CST 2018
获得写锁:Thread-1:Sun Oct 28 18:50:34 CST 2018
取消写锁:Thread-1:Sun Oct 28 18:50:44 CST 2018
写读结果:
获得写锁:Thread-0:Sun Oct 28 18:53:15 CST 2018
取消写锁:Thread-0:Sun Oct 28 18:53:25 CST 2018
获得读锁:Thread-1:Sun Oct 28 18:53:25 CST 2018
取消读锁:Thread-1:Sun Oct 28 18:53:35 CST 2018
结论是:只要有写操作的过程,都是互斥的。