Java中的ReentranReadWriteLock

    类ReentranLock具有完全互斥排他的效果,即同一时间只有一个线程在执行ReentranLock.lock方法后面的任务。这样做虽然保证了实例变量的线程安全性,但效率确是非常低下的。所以引入了一种读写锁ReentranReadWriteLock类,使用它可以加快运行效率。

    读写锁表示也有两个锁,一个是读操作相关的锁,也称为共享锁;另一个是写操作相关的锁,也叫排它锁。也就是多个读锁之间不互斥,读锁与写锁互斥,写锁与写锁互斥。

一、读读共享

public class Test5 {
    public static void main(String[] args) {
        ServiceRR serviceRR = new ServiceRR();
        Thread t1 = new Thread(){
            @Override
            public void run() {
                serviceRR.read();
            }
        };
        Thread t2 = new Thread(){
            @Override
            public void run() {
                serviceRR.read();
            }
        };
        Thread t3 = new Thread(){
            @Override
            public void run() {
                serviceRR.read();
            }
        };
        t1.start();
        t2.start();
        t3.start();
    }
}
class ServiceRR{
    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    public void read(){
        try {
            try {
                lock.readLock().lock();
                System.out.println(Thread.currentThread().getName()+"获得读锁");
                Thread.sleep(2000);
            }finally {
                lock.readLock().unlock();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
上述代码有三个线程,都在同时进行读操作。

    

由结果来看,read方法中获得读锁后休眠1秒,此时未释放锁,而此时其他两个线程也进入了read方法并获得了读锁。可见读读是共享的。

二、写写互斥

public class Test6 {
    public static void main(String[] args) {
        ServiceWW serviceWW = new ServiceWW();
        Thread t1 = new Thread(){
            @Override
            public void run() {
                serviceWW.write();
            }
        };
        Thread t2 = new Thread(){
            @Override
            public void run() {
                serviceWW.write();
            }
        };
        Thread t3 = new Thread(){
            @Override
            public void run() {
                serviceWW.write();
            }
        };
        t1.start();
        t2.start();
        t3.start();
    }
}
class ServiceWW{
    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    public void write(){
        try {
            try {
                lock.writeLock().lock();
                System.out.println(Thread.currentThread().getName()+"获得写锁");
                Thread.sleep(2000);
            }finally {
                lock.writeLock().unlock();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

上述代码有三个线程进行写操作


Thread-1休眠2秒钟期间没有线程获得写锁


Thread-0休眠完后,Thread-1获得写锁,在Thread-1休眠期间,最后一个线程也没有获得写锁


Thead-0和Thread-1都执行完后,Thread-2才获得写锁。由此可见写写是互斥的。

三、读写互斥

public class Test7 {
    public static void main(String[] args) {
        ServiceRW serviceRW = new ServiceRW();
        Thread t1 = new Thread(){
            @Override
            public void run() {
                serviceRW.read();
            }
        };
        Thread t2 = new Thread(){
            @Override
            public void run() {
                serviceRW.write();
            }
        };
        t1.start();
        t2.start();
    }
}
class ServiceRW{
    private ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
    public void read(){
        try {
            try {
                lock.readLock().lock();
                System.out.println(Thread.currentThread().getName()+"获得读锁");
                Thread.sleep(2000);
            }finally {
                lock.readLock().unlock();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    public void write(){
        try {
            try {
                lock.writeLock().lock();
                System.out.println(Thread.currentThread().getName()+"获得写锁");
                Thread.sleep(2000);
            }finally {
                lock.writeLock().unlock();
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}
上述代码是一个读操作线程和一个写操作线程



可见,Thread-0获得读锁然后休眠时,写操作线程无法获取到写锁,可见读写是互斥的。

四、写读互斥

将读写互斥的代码的线程启动顺序交换,便是写读互斥,运行结果如下



可见,Thread-1获得写锁然后休眠时,读操作线程无法获取到写锁,可见写读是互斥的。

五、总结

    读写,写读,写写都是互斥的,而读读是异步的,非互斥的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值