专栏首页立权的博客重量级锁的加锁-等待-撤销流程

重量级锁的加锁-等待-撤销流程

上述有三个队列,这些队列中的节点,都是线程包装成的 ObjectWaiter

在默认策略情况下:

1.entry_list 中的 节点是等待被唤醒的节点,持有重量级锁的线程执行 exit 方法(Java层面:退出上述 synchronized区或调用 wait()方法 会调用 (C++层面)exit方法),exit方法会唤醒 本队列的头节点(unpark),避免惊群

2.cxq_list 中的 节点是 获取锁失败后的线程的节点,exit 方法会检查 entry_list 是否为空,如果是空的,就会从 cxq_list 中拿 节点,放到 entry_list,放入顺序默认是 把 cxq_list 直接插到 entry_list 后面

3.wait_set 是调用 java 层面的 wait() 方法 的线程 该待的地方,需要注意的是 ,只有 notify 和 notifyAll 能够把 wait_set 中的节点 移入到 cxq_list (默认是把 cxq_list 插入到 wait_set 后面,wait_set 做为新的 cxq_list)

下面这个案例中,执行 a 的线程不会被唤醒。因为执行 b 的线程退出 sychronized 区只是 调用了 c++ 层面的 exit 方法,没有把 wait_set 中的 执行 a 的线程 放入到 cxq_list

调用 notify 和 notifyAll 方法 不会让 wait_set 里的线程 被 unpark ,只是让他们移入 cxq_list。

     Runnable a = () -> {
            synchronized (lock) {
                System.out.println("working");
                try {
                    lock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("finalize");
            }
        };

        Runnable b = () -> {
            synchronized (lock) {
                System.out.println("doSomething");
            }
            System.out.println("done");
        };
        new Thread(a).start();
        Thread.sleep(1000);
        new Thread(b).start();

默认的 cxq_list 进入 entry_list 的方式:

默认的 wait_set 节点进入 cxq_list 的方式(notifyAll)

默认的 wait_set 节点进入 cxq_list 的方式(notify)

也就是,如果有一个线程 a 先进入 synchronized , 但是调用了 wait,这是线程 b 进入了 synchronized,b还在synchronized中执行,c线程又进来了。

此时 a 在 wait_set ,b 不在任何队列,c 在 cxq_list ,假如 b 调用 notify,会把 a 插到 c 前面,也就是 b 退出synchronized的时候,会唤醒 a,a退出之后再唤醒 c

也就是 曾经获得过锁的线程 被唤醒后 优先得到锁

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Hadoop架构: HDFS中数据块的状态及其切换过程,GS与BGS

    该系列总览: Hadoop3.1.1架构体系——设计原理阐述与Client源码图文详解 : 总览

    执生
  • 栈论 : 递归与栈式访问,如何用栈实现所有递归操作(幼儿园题目篇)

    找出二叉树中成员变量M为a 和 b 的节点的最小祖先节点(假设a b 只出现一次)

    执生
  • 关于page_struct中virtual指针的思考

    其中 virtual 居然直接 指向物理页面的起始地址,不是单单根据图推断的,文章内容也是这么描述的

    执生
  • 详解JavaScript跨域问题

    什么是跨域? 概念:只要协议、域名、端口有任何一个不同,都被当作是不同的域。 URL 说明 是否允许通信 ...

    前朝楚水
  • 跨域详解

    csxiaoyao
  • 技术管理者带团队的几个实用技巧

    个人从程序员到技术 Leader 经历了不少的心路历程,我目前在带一支十几人的技术团队(控制团队人数主要是遵循亚马孙 CEO 贝索斯提出的两个披萨原则)我记得刚...

    phoenix.xiao
  • 2020年| 最新自动驾驶数据集汇总,持续更新(2)

    论文名称:nuScenes: Amultimodal dataset for autonomous driving

    CNNer
  • 大数据24小时 | 沈阳发布“大数据三年计划” 麻省理工学院推出可视化工具“数据美国”

    麻省理工学院推出大数据可视化工具——“数据美国” ? 近日,麻省理工学院推出了一个 “数据美国”在线大数据可视化工具 ,可以实时分析展示美国政府公开数据库(Op...

    数据猿
  • Python 破解极验滑动验证码

    以上图片是最典型的要属于极验滑动认证了,极验官网:http://www.geetest.com/。

    测试开发社区
  • 确认过眼神,这就是你要的路由库

    上一篇文章我们谈到了如何实现一个路由库,那本篇文章就给大家推荐一个好用的路由库,来确认下眼神,这就是你要的路由库。

    用户2898788

扫码关注云+社区

领取腾讯云代金券