Java多线程之wait(),notify(),notifyAll()

Java多线程之wait(),notify(),notifyAll()

大家好,又见面了,我是全栈君,祝每个程序员都可以多学几门语言。

在多线程的情况下,因为同一进程的多个线程共享同一片存储空间,在带来方便的同一时候,也带来了訪问冲突这个严重的问题。Java语言提供了专门机制以解决这样的冲突,有效避免了同一个数据对象被多个线程同一时候訪问。

   wait与notify是java同步机制中重要的组成部分。结合与synchronizedkeyword使用,能够建立非常多优秀的同步模型。
  synchronized(this){ }等价于publicsynchronized void method(){…..}
   同步分为类级别和对象级别,分别相应着类锁和对象锁。类锁是每一个类仅仅有一个,假设static的方法被synchronizedkeyword修饰,则在这种方法被运行前必须获得类锁;对象锁类同。
   首先,调用一个Object的wait与notify/notifyAll的时候,必须保证调用代码对该Object是同步的,也就是说必须在作用等同于synchronized(obj){……}的内部才可以去调用obj的wait与notify/notifyAll三个方法,否则就会报错:
  java.lang.IllegalMonitorStateException:current thread not owner
  在调用wait的时候,线程自己主动释放其占有的对象锁,同一时候不会去申请对象锁。当线程被唤醒的时候,它才再次获得了去获得对象锁的权利。
  所以,notify与notifyAll没有太多的差别,仅仅是notify仅唤醒一个线程并同意它去获得锁,notifyAll是唤醒全部等待这个对象的线程并同意它们去获得对象锁,仅仅要是在synchronied块中的代码,没有对象锁是寸步难行的。事实上唤醒一个线程就是又一次同意这个线程去获得对象锁并向下执行。

   notifyAll,尽管是对每一个wait的对象都调用一次notify,可是这个还是有顺序的,每一个对象都保存这一个等待对象链,调用的顺序就是这个链的顺序。事实上启动等待对象链中各个线程的也是一个线程,在详细应用的时候,须要注意一下。

  wait(),notify(),notifyAll()不属于Thread类,而是属于Object基础类,也就是说每一个对像都有wait(),notify(),notifyAll()的功能。由于都个对像都有锁,锁是每一个对像的基础,当然操作锁的方法也是最基础了。

wait():

等待对象的同步锁,须要获得该对象的同步锁才干够调用这种方法,否则编译能够通过,但执行时会收到一个异常:IllegalMonitorStateException。

调用随意对象的 wait() 方法导致该线程堵塞,该线程不可继续运行,而且该对象上的锁被释放。

notify():

唤醒在等待该对象同步锁的线程(仅仅唤醒一个,假设有多个在等待),注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,并且不是按优先级。

调用随意对象的notify()方法则导致因调用该对象的 wait()方法而堵塞的线程中随机选择的一个解除堵塞(但要等到获得锁后才真正可运行)。

notifyAll():

唤醒全部等待的线程,注意唤醒的是notify之前wait的线程,对于notify之后的wait线程是没有效果的。

 

通常,多线程之间须要协调工作:假设条件不满足,则等待;当条件满足时,等待该条件的线程将被唤醒。在Java中,这个机制的实现依赖于wait/notify。等待机制与锁机制是密切关联的。

比如:
  synchronized(obj) {
  while(!condition) {
  obj.wait();
  }
  obj.doSomething();
  }
  
  当线程A获得了obj锁后,发现条件condition不满足,无法继续下一处理,于是线程A就wait()。
  在还有一线程B中,假设B更改了某些条件,使得线程A的condition条件满足了,就能够唤醒线程A :
  
  synchronized(obj) {
  condition = true;
  obj.notify();
  }
  
  须要注意的概念是:
  
  # 调用obj的wait(), notify()方法前,必须获得obj锁,也就是必须写在synchronized(obj){…} 代码段内。

  
  # 调用obj.wait()后,线程A就释放了obj的锁,否则线程B无法获得obj锁,也就无法在synchronized(obj){…} 代码段内唤醒A。
  
  # 当obj.wait()方法返回后,线程A须要再次获得obj锁,才干继续运行。
  
  #假设A1,A2,A3都在obj.wait(),则B调用obj.notify()仅仅能唤醒A1,A2,A3中的一个(详细哪一个由JVM决定)。
  
  #obj.notifyAll()则能所有唤醒A1,A2,A3,可是要继续运行obj.wait()的下一条语句,必须获得obj锁,因此,A1,A2,A3仅仅有一个有机会获得锁继续运行,比如A1,其余的须要等待A1释放obj锁之后才干继续运行。
  
  # 当B调用obj.notify/notifyAll的时候,B正持有obj锁,因此,A1,A2,A3虽被唤醒,可是仍无法获得obj锁。直到B退出synchronized块,释放obj锁后,A1,A2,A3中的一个才有机会获得锁继续运行。
  

谈一下synchronized和wait()、notify()等的关系:

1.有synchronized的地方不一定有wait,notify

2.有wait,notify的地方必有synchronized.这是由于wait和notify不是属于线程类,而是每个对象都具有的方法,并且,这两个方法都和对象锁有关,有锁的地方,必有synchronized。

另外,注意一点:假设要把notify和wait方法放在一起用的话,必须先调用notify后调用wait,由于假设调用完wait,该线程就已经不是currentthread了。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/118813.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • pocib业务流程图_财务流程图

    pocib业务流程图_财务流程图POCIB各阶段流程报关流程从广义上讲,报关是指进出境运输工具负责人、进出境口货物收发货人、进出境物品的所有人或者他们的代理人向海关办理运输工具、货物、物品进出境手续及相关手续的全过程。其中,进出境运输工具负责人、进出口货物收发货人、进出境物品的所有人或者他们的代理人是报关行为的承担者,是报关的主体,也就是报关人,也称报关单位。这里所指的报关人既包括法人和其他组织,比如进出口企业、报关企业,也包括…

  • 从box-sizing:border-box属性入手,来了解盒模型

    从box-sizing:border-box属性入手,来了解盒模型从最开始学习CSS的时候,就了解了盒模型的概念,今天,我们从其中的box-sizing:border-box;的属性入手,来重新认识一下盒模型在实际项目中的运用。背景:先声明一下运用的场景,假如项目布局使用的是自适应的布局方式,div给出的宽度是百分比的形式,即框占窗口宽度的50%,但边界和内边距是用像素来表示的怎么办?为了避免这种问题,可以使用属性box-sizing来调整框…

  • 如何解决360浏览器被hao.360.cn主页劫持问题

    如何解决360浏览器被hao.360.cn主页劫持问题360这家公司很奇葩,以流氓软件起家,后面转型为反流氓软件公司,目标是把你电脑上的其他流氓软件干掉,只留下自己家的流氓软件,所以本质没变。但是360家的浏览器易用性还可以,虽然基于GoogleChr

  • arm指令周期_arm指令sub

    arm指令周期_arm指令sub1.大部分算术运算和逻辑运算指令都是单周期的,例如加法、减法、位级运算和移位2.乘法指令根据操作数位数的不同,从2-5个周期都有可能。3.无条件跳转语句和跳转语句成功跳转,需要重新填充流水线,因此至少需要3个周期4.跳过条件不满足的指令只需要花1个周期(以上周期应该是指各指令包含的机器周期数)时钟周期:振荡周期,即CPU主频。机器周期:又称CPU周期,完…

  • java分割String字符串成list

    java分割String字符串成list示例:Stringsn=“1234,567,8910”;List<String>snList=Arrays.asList(sn.split(“,”));

  • Unity3D 2018安装教程[通俗易懂]

    Unity3D 2018安装教程[通俗易懂]安装步骤:安装前先关闭杀毒软件和360卫士,注意安装路径不能有中文,安装包路径也不要有中文。试装系统:win1064bit安装版本:Unity2018.3.0重要:Unity2018.3.0相较2017版本的在启动时稳定了很多(2017版本启动经常会卡在loading界面)如果启动Unity2018.3.0时一直卡在loading界面进不去,可以尝试以下两种解决办法:1.1:将计算…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号