超越地域和文化,AI识别出全人类共同的16种面部表情
|
wait
注意两个队列: 等待队列:notifyAll/notify唤醒的就是等待队列中的线程; 同步线程:就是竞争锁的所有线程,等待队列中的线程被唤醒后进入同步队列。 sleep与wait的区别 sleep
简单的说,当多个线程竞争访问同一段同步代码块时,如果线程获取到了 monitor,那么就会把 _owner 设置成当前线程,如果是重入的话,_recursions 会加 1,如果获取 monitor 失败,则会进入 _cxq队列。 锁被释放时,_cxq中的线程会被移动到 _EntryList中,并且唤醒_EntryList 队首线程。当然,选取唤醒线程有几个不同的策略(Knob_QMode),还是后面结合源码解析。 「注」:_cxq和 _EntryList本质上是ObjectWaiter 类型,它本质上其实是一个双向链表 (具有前后指针),只是在使用的时候不一定要当做双向链表使用,比如 _cxq 是当做单向链表使用的,_EntryList是当做双向链表使用的。 什么场景会导致线程的上下文切换?
导致线程上下文切换的有两种类型: 从上图中我们可以看出,如果对象处于未锁定状态(无锁态),那么 Mark Word 的 25 位用于存储对象的哈希码,4 位用于存储对象分代年龄,1 位固定为 0,两位用于存储锁标志位。 这个图对于理解后面提到的轻量级锁、偏向锁是非常重要的,当然我们现在可以先着重考虑对象处于重量级锁状态下的情况,也就是锁标志位为 10。同时我们看到,无锁态和偏向锁状态下,2 位锁标志位都是“01”,留有 1 位表示是否可偏向,我们姑且叫它“偏向位”。 「注」:对象头的另一部分则是类型指针,虚拟机可以通过这个指针来确认该对象是哪个类的实例。但是我们要注意,并不是所有的虚拟机都必须以这种方式来确定对象的元数据信息。对象的访问定位一般有句柄和直接指针两种,如果使用句柄的话,那么对象的元数据信息可以直接包含在句柄中(当然也包括对象实例数据的地址信息),也就没必要将这些元数据和实例数据存储在一起了。至于实例数据和对齐填充,这里暂不做讨论。
前面我们提到了,Java 中的每个对象都与一个 monitor 相关联,当锁标志位为 10 时,除了 2bit 的标志位,指向的就是 monitor 对象的地址(还是以 32 位虚拟机为例)。这里我们可以翻阅一下 OpenJDK 的源码,如果我们需要下载openJDK的源码: (编辑:惠州站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
