并发编程-读写锁的读读并发理解

并发编程之读写锁的读读并发的理解

代码例子

@Slf4j(topic = "liheng")
public class Lock2 {
    //读写锁
    static ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();

    static Lock r = rwl.readLock();
    static Lock w = rwl.writeLock();

    public static void main(String[] args) throws InterruptedException {

        /**
         * t1  最先拿到写(W)锁 然后睡眠了5s
         * 之后才会叫醒别人
         */
        Thread t1 = new Thread(() -> {
            w.lock();

            try {
                log.debug("t1 +");
                TimeUnit.SECONDS.sleep(5);
                log.debug("5s 之后");
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                w.unlock();
            }
        }, "t1");

        t1.start();

        TimeUnit.SECONDS.sleep(1);


        /**
         * t1在睡眠的过程中 t2不能拿到 读写互斥
         * t2 一直阻塞
         */
        Thread t2 = new Thread(() -> {
            try {
                r.lock();
                log.debug("t2----+锁-------");
                TimeUnit.SECONDS.sleep(1);
            } catch (Exception e) {

                e.printStackTrace();
            } finally {
                log.debug("t2-----解锁-------");
                r.unlock();
            }
        }, "t2");
        t2.start();

        TimeUnit.SECONDS.sleep(1);


        /**
         * t1在睡眠的过程中 t3不能拿到 读写互斥
         * t3 一直阻塞
         *
         * 当t1释放锁之后 t3和t2 能同时拿到锁
         * 读读并发
         */
        Thread t3 = new Thread(() -> {
            try {
                r.lock();
                log.debug("t3----+锁-------");
                TimeUnit.SECONDS.sleep(1);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                log.debug("t3----释放-------");

                r.unlock();
            }
        }, "t3");
        t3.start();

        /**
         * 拿写锁
         * t1睡眠的时候 t4也页阻塞
         * 顺序应该 t2 t3  t4
         */

        Thread t4 = new Thread(() -> {
            try {
                w.lock();
                log.debug("t4--------+---");
                TimeUnit.SECONDS.sleep(10);
                log.debug("t4--------醒来---");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                log.debug("t4--------解锁---");
                w.unlock();
            }
        }, "t4");

        t4.start();

        /**
         *
         * t5 是读锁
         * 他会不会和t2 t3 一起执行
         */

        Thread t5 = new Thread(() -> {
            try {
                r.lock();
                log.debug("t5--------+锁---");
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                log.debug("t5--------解锁---");
                r.unlock();
            }
        }, "t5");

        t5.start();
    }
}

代码结果:

15:07:12.915 [t1] DEBUG liheng - t1 +
15:07:17.922 [t1] DEBUG liheng - 5s 之后
15:07:17.923 [t2] DEBUG liheng - t2----+锁-------
15:07:17.923 [t3] DEBUG liheng - t3----+锁-------
15:07:18.925 [t2] DEBUG liheng - t2-----解锁-------
15:07:18.928 [t3] DEBUG liheng - t3----释放-------
15:07:18.928 [t4] DEBUG liheng - t4--------+---
15:07:28.932 [t4] DEBUG liheng - t4--------醒来---
15:07:28.933 [t4] DEBUG liheng - t4--------解锁---
15:07:28.933 [t5] DEBUG liheng - t5--------+锁---
15:07:28.933 [t5] DEBUG liheng - t5--------解锁---

Process finished with exit code 0

结果分析:t1写锁,拿到锁,睡眠5秒,这时其他线程park。t1释放锁,按照FIFO的原则唤醒t2读锁,t2判断t3是否是读锁,因为t3是对锁,所以t3也被唤醒,t3判断t4不是读锁,所以没有唤醒t4,可以看到结果t2,t3是被同时在15:07:17.923唤醒的,然后t2,t3执行同步块释放锁。t4写锁拿到锁,t4执行同步代码块,释放锁,t5读锁拿到锁,执行同步代码块,然后释放锁,程序结束。

总结:比如先有一个t1写锁拿到锁,后面有一些其他锁或许是读或许是写在park;当t1释放锁之后按照FIFO的原则唤醒等待的线程;如果第一个被唤醒的是t2写锁则无可厚非;不会再跟着唤醒t3,只有等t2执行完成之后才会去唤醒T3;假设被唤醒的t3是读锁,那么t3会去判断他的下一个t4是不是读锁如果是则把t4唤醒;t4唤醒之后会判断t5是不是读锁;如果t5也是则唤醒t5;依次类推;但是假设t6是写锁则不会唤醒t6了;即使后面的t7是读锁也不会唤醒t7;

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

半路笙歌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值