3.4wait的条件发生变化导致逻辑错误
来源:互联网 发布:子曰由诲女知之乎翻译 编辑:程序博客网 时间:2024/06/07 01:50
若wait的条件需要发生变化是,需要注意程序逻辑的变化
下面有个错误例子
package com.myObject;public class AddObject { private String lock; public AddObject(String lock) { this.lock = lock; } public void add() { synchronized (lock) { ValueObject.list.add("anyStr"); lock.notifyAll(); } }}
package com.myObject;public class SubObject { private String lock; public SubObject(String lock) { this.lock = lock; } public void sub(){ synchronized(lock){ try { if(ValueObject.list.size()==0){//注意wait条件的变化 System.out.println(Thread.currentThread().getName()+" wait begin " + System.currentTimeMillis()); lock.wait(); System.out.println(Thread.currentThread().getName()+" wait end " + System.currentTimeMillis()); } ValueObject.list.remove(0); System.out.println("list size "+ValueObject.list.size()); } catch (InterruptedException e) { e.printStackTrace(); } } }}
package com.myObject;import java.util.ArrayList;import java.util.List;public class ValueObject {public static List list= new ArrayList();}
package com.myThread;import com.myObject.AddObject;public class Thread1a extends Thread { AddObject addObject; public Thread1a(AddObject addObject) { this.addObject = addObject; } @Override public void run() { addObject.add(); }}
package com.myThread;import com.myObject.SubObject;public class Thread1b extends Thread { SubObject subObject; public Thread1b(SubObject subObject) { this.subObject = subObject; } @Override public void run() { subObject.sub(); }}
package com.test;import com.myObject.AddObject;import com.myObject.SubObject;import com.myThread.Thread1a;import com.myThread.Thread1b;public class Test1 { public static void main(String[] args) throws InterruptedException{ String lock = new String("hello"); AddObject addObject = new AddObject(lock); SubObject subObject = new SubObject(lock); Thread1a thread1a = new Thread1a(addObject); thread1a.setName("add"); Thread1b thread1b1 = new Thread1b(subObject); Thread1b thread1b2 = new Thread1b(subObject); thread1b1.setName("sub1"); thread1b2.setName("sub2"); thread1b1.start(); thread1b2.start(); Thread.sleep(2000); thread1a.start(); }}
打印结果
sub2 wait begin 1453104941268
sub1 wait begin 1453104941268
sub1 wait end 1453104943268
Exception in thread "sub2" list size 0
sub2 wait end 1453104943269
java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.RangeCheck(ArrayList.java:547)
at java.util.ArrayList.remove(ArrayList.java:387)
at com.myObject.SubObject.sub(SubObject.java:18)
at com.myThread.Thread1b.run(Thread1b.java:14)
结果分析:当sub1和sub2分别在wait之前,进行了一次判断,那时的条件都是“ValueObject.list.size()==0”,但被唤醒之后并没有再次进行判断,就继续往下执行了,然后判断的条件已经发生改变了,所以导致List的索引溢出
解决方法:这里的解决方法时使用while,把if改为while
打印结果
sub2 wait begin 1453106550825
sub1 wait begin 1453106550825
sub1 wait end 1453106552825
list size 0
sub2 wait end 1453106552826
sub2 wait begin 1453106552826
结果分析:sub1和sub2都被唤醒,sub1抢先得到资源然后使得“ValueObject.list.size()==1”退出循环,sub2紧接着得到资源,但sub2得到资源时sub1已经把ValueObject.list.size()变为0了,所以sub2继续循环然后又进入wait
- 3.4wait的条件发生变化导致逻辑错误
- 3.1.10等待wait的条件变化
- liferay升级到5.1后类的路径发生变化导致的错误
- 开发环境的变化导致的编译错误
- Android ListView避免在GetView时数据发生变化导致找不到元素的Bug
- 还在爬山吗?得知恨晚!长时间爬山导致人体发生的变化,不可不看
- 死锁发生的条件
- 死锁发生的条件
- #1#条件的逻辑
- 条件判断的逻辑
- 【OGG-01161】源端表结构发生变化导致replicat进程abend
- setChannel发生错误导致无法通话录音
- /etc/fstab发生错误或磁盘错误导致系统无法启动的修复方法
- /etc/fstab发生错误或磁盘错误导致系统无法启动的修复方法
- response.sendRedirect("cn/jsp/index.jsp")跳转之后地址会发生变化,导致servlet的链接无效
- 常见的容易发生变化的区域
- android发生的错误
- statement发生的错误
- xcode7 没有Empty Application
- 递归算法的魅力所在——图的遍历
- eclipse下导入jdk源码
- 关于jquery中on方法的一些介绍
- MTTR是什么?或者说为什么别给婴儿喝白兰地
- 3.4wait的条件发生变化导致逻辑错误
- struts2标签和jstl标签混和使用
- 来,让我们写一个网络爬虫,下载页面上所有的照片吧!
- 统一初始化语法
- 多态基类与虚析构函数
- 如何来写好一个赋值运算符函数
- 《将博客搬至CSDN》
- 如何判断循环链表
- Python流控制- 逻辑运算符