• 欢迎访问搞代码网站,推荐使用最新版火狐浏览器和Chrome浏览器访问本网站!
  • 如果您觉得本站非常有看点,那么赶紧使用Ctrl+D 收藏搞代码吧

关于java:浅谈synchronized与Objectwaitnotify原理

java 搞代码 3年前 (2022-02-19) 33次浏览 已收录 0个评论

synchronized是Java中罕用的锁机制,synchronized+Object.wait/notify是罕用的期待唤醒机制,那它们的实现原理是什么呢?本文就synchronized与Object.wait/notify为例谈谈以下内容。

  • synchronized锁降级。
  • synchronized是如何工作的。
  • synchronized同步队列和期待队列是如何配合的。
  • 为什么Object.wait必须在synchronized中。

synchronized在JVM里的实现是基于进入和退出Monitor对象来实现办法同步和代码块同步的。monitor enter指令是在编译后插入到同步代码块的开始地位,而monitor exit是插入到办法完结处和异样处,JVM要保障每个monitor enter必须有对应的monitor exit与之配对。任何对象都有一个monitor与之关联,当且一个monitor被持有后,它将处于锁定状态。

Java 1.6为了缩小取得锁和开释锁带来的性能耗费,引入了“偏差锁”和“轻量级锁”,在Java SE 1.6中,锁一共有4种状态,级别从低到高顺次是:无锁状态偏差锁状态轻量级锁状态重量级锁状态,这几个状态会随着竞争状况逐步降级。

留神:synchronized能够润饰某个办法,也能够润饰某个对象。

执行monitor enter指令如果获取锁不胜利,会将该线程增加到该monitor对象对应的同步队列 SynchronizedQueue,当占用该monitor对象的线程执行monitor out时就会唤醒同步队列中的线程。

那么问题来了,唤醒线程时是抉择同步队列上哪一个线程呢?java8默认抉择最近增加到同步队列中的那个线程。能够应用如下代码验证:

<code class="java">private static Object obj = new Object();

public static void main(String[] args) throws Exception {
    synchronized (obj) {
        newThread("t1");
        newThread("t2");
        newThread("t3");
        newThread("t4");
        newThread("t5");

        Thread.sleep(1000);
        System.out.println("main release");
    }

    System.out.println("main end");
    Thread.sleep(2000);
}

private static void newThread(String name) throws Exception {
    new Thread(() -> {
        synchronized (obj) {
            System.out.println(Thread.currentThread().getName() + " get");
        }
    }, name).start();
    Thread.sleep(100L);
}
复制代码

输入后果为:

同步队列和期待队列

晓得了synchronized基本概念之后,一起来看下Object.wait()/notify(),Monitor对象 中蕴含一个同步队列(由 _cxq_EntryList 组成)和一个期待队列( _WaitSet )。

  • 被notify或 notifyAll 唤醒时依据 policy 策略抉择退出的队列(policy 默认为 0)
  • 退出同步块时依据 QMode 策略来唤醒下一个线程(QMode 默认为 0)

留神:synchronized的同步队列和期待队列 与 基于AQS(lock/condition)的同步队列和期待队列实现原理相似,只不过前者是一个同步队列对应一个期待队列,而后者是一个同步队列能够对应多个期待队列。

synchronized的同步队列和期待队列流程图如下所示:

到这里为止,咱们大抵理解了synchronized是如何工作的,以及它的同步队列和期待队列是如何配合的。

最初咱们思考2个问题:

1、为什么要有Object.wait/notify,只应用synchronized不能也能实现线程阻塞而后被其余线程唤醒(告诉)么

2、执行Object.wait/notify,为什么必须要在synchronized中呢

这里小伙伴们略微劳动片刻,思考下上述2个问题的起因。

对于第一个问题,只应用synchronized是为了简略的加解锁,而应用Object.wait/notify 是为了实现被告诉后,再执行下一步动作的逻辑。如果Object.wait后没有任何逻辑的话,这里的Object.wait是没有意

来源gaodai.ma#com搞##代!^码网

义的,能够间接去掉。

对于第二个问题,为什么必须要在synchronized中呢,咱们都晓得synchronized锁机制大都是为了保障原子性,因而咱们有理由置信,这里的起因大概率就是原子性。那么是为了什么的原子性呢?是为了保障在Object.wait时,将以后线程增加到_WaitSet期待队列和monitor out唤醒其余线程的原子性;为了保障在Object.notify 时,在将以后线程从WaitSet移到同步队列时,锁相干的线程状态不会发生变化。

参考:《2020最新Java根底精讲视频教程和学习路线!》
链接:https://juejin.cn/post/694228…


搞代码网(gaodaima.com)提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发送到邮箱[email protected],我们会在看到邮件的第一时间内为您处理,或直接联系QQ:872152909。本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:关于java:浅谈synchronized与Objectwaitnotify原理

喜欢 (0)
[搞代码]
分享 (0)
发表我的评论
取消评论

表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址