notify和notifyall的一段代码分析-java开发java经验技巧

notify和notifyall的一段代码分析-java开发java经验技巧

ID:30789196

大小:72.00 KB

页数:5页

时间:2019-01-03

notify和notifyall的一段代码分析-java开发java经验技巧_第1页
notify和notifyall的一段代码分析-java开发java经验技巧_第2页
notify和notifyall的一段代码分析-java开发java经验技巧_第3页
notify和notifyall的一段代码分析-java开发java经验技巧_第4页
notify和notifyall的一段代码分析-java开发java经验技巧_第5页
资源描述:

《notify和notifyall的一段代码分析-java开发java经验技巧》由会员上传分享,免费在线阅读,更多相关内容在工程资料-天天文库

1、notify和notifyAH的一段代码分析-编程开发技术notify和notifyAll的一段代码分析木文由ImportNew■踏雁寻花翻译自stackoverflow0欢迎加入翻译小组。转载请见文末要求。【本文已经根据网友的意见,进行了修改,考虑到网友会看不懂评论内容,我将本文的第一版发布到了博客屮,点击这里?踏雁寻花?可以阅读。?】根据网友的意见,修改版如下:当你Google,,notify()和notifyAll()的区别”时,会有大片的结果弹出来,(这里先把jdk的javadoc文档那一段撇开不说),所冇这些搜索结果归结为等待的线程被唤醒的数量:notify()是唤醒一个

2、,而notifyallO是唤醒全部•那他们的真正区别是什么呢?让我们来看看个生产者/消费者的案例(假设生产者/消费者这个类中有两个方法put和get),它是有问题的(因为这里用到了notify方法),是的,这段代码也许会执行,甚至大部分情况下能够正常运行,但是它也是冇可能会出发生死锁,我们來看一看原因:publicsynchronizedvoidput(Objecto){while(buf.size()二二MAX_SIZE){wait();//如果buffer为full,就会执行wait方法等待(为了简单,我们省略try/catch语句块)}buf.add(o);notify();

3、//通知所有止在等待对象锁的Producer和Consumer(译者注:包括被阻挡在方法外的Producer和Consumer)}//Y:这里是C2试图获取锁的地方(原作者将这个方法放到了get方法里面,此处,我把它放在了方法的外面)publicsynchronizedObjectget(){while(buf.size()==0){wait();//如果buffer为Null,就会执行wait方法(为了简单,同样省略try/catch语句块)//X:这里是C1试图重新获得锁的地方(看下面代码)}Objecto=buf.remove(0);notify();//通知所有正在等待对象

4、锁的Producer和Consumer(译者注:包括被阻挡在方法外的Producer和Consumer)returno;首先我们为什么在wait方法外面加上while循环?我们需要使用while循坏來实现卜•面的情呆,情景分析:消费者1(C1)进入同步块中,此时buf是空的,所以C1被放入wait队列中(因为执行了wait方法,译者注:此时C2是恰好到方法处,而不是因为有线程在方法屮运行才被阻挡在方法外的),当消费者2(C2)正要进入同步方法的时候(此时在Y的上血),生产者P1将一个对彖放入到buf中,随后又调用notify方法。此时wait队列中唯一的线程是Cl(译者注:C2不在

5、waiting队列屮,也不在blocked队列中),所以C1被唤醒,C1被唤醒之后又开始试图重新获得对象锁,此吋C1还在X的上而。现在的情况是,C1和C2都在试图去获取同步锁,这两个线程只能有一个被选择进入方法,另一个则会被堵塞(不是waiting,而是blocked<>译者注:虽然C1已经在方法屮,不过还是会和C2竟争锁,如果C2获得锁,则C2进入方法执行接下来的操作,而C1还是继续等待锁(处于blocked状态);如果C1获得锁,则C1往下执行,而C2还是会被挡在方法外而(处于blocked状态))。假如C2先获得了对象锁,C1仍然被阻挡着(此吋C1还试图在X处获得锁),C2完

6、成了方法,并释放了锁。现在C1获得了锁。假设这里没有while循环,那么C1就会往下执行,从buf屮删除一个对象,但是此时buf中已经没有对象了,因为刚刚C2已经取走了一个对象,如果此时C1执行buf.remove(O),则会报IndexArrayOutOfBoundsExceptionJrf*常。为了防止这样的异常发生,我们在上面用到了while循环,在往下执行Z前,判断此时buf的大小是否为0,如果不是0,则往下执行,如果是0,则继续wait()o那么我们这里引出问题:为什么需要notifyAll?在上面生产者-消费者这个例子中,看起来我们用notify也能够侥幸成功,因为等待

7、循坏的哨兵对于消费者和生产者來说是互斥的。我们不能同时在put方法和get方法都有一个线程勰it,如果这种情况允许的话,那么下而的事情就会发生:buf.sizeO==0ANDbuf.size()==MAX_S1ZE(假设MAX_S1ZE不为0)然而,这样并不好,我们需要使用notifyAllo让我们来看一看原因:假设buffer二1(为了更加容易理解),按照下面的步骤执行将会发生死锁。要注意的是:notify可以唤醒任何一个线程,不过JVM不能确定是哪个线程被唤醒,所

当前文档最多预览五页,下载文档查看全文

此文档下载收益归作者所有

当前文档最多预览五页,下载文档查看全文
温馨提示:
1. 部分包含数学公式或PPT动画的文件,查看预览时可能会显示错乱或异常,文件下载后无此问题,请放心下载。
2. 本文档由用户上传,版权归属用户,天天文库负责整理代发布。如果您对本文档版权有争议请及时联系客服。
3. 下载前请仔细阅读文档内容,确认文档内容符合您的需求后进行下载,若出现内容与标题不符可向本站投诉处理。
4. 下载文档时可能由于网络波动等原因无法下载或下载错误,付费完成后未能成功下载的用户请联系客服处理。