package calc; /** * @author : S K Y * @version :0.0.1 */ class Resource { //定义一个操作的资源 private int num = 0; //定义要进行加减操作的数据 /*flag = true 表示可以进行加法操作,无法进行减法操作 * flag = false 表示可以进行减法操作,无法进行加法操作*/ private boolean flag = true; public synchronized void add() throws InterruptedException { if (!this.flag) { //现在需要执行的是减法操作,加法操作需要等待 super.wait(); } Thread.sleep(100); this.num++; System.out.println("[加法操作-" + Thread.currentThread().getName() + "]num = " + this.num+ " " + this.flag); this.flag = false; super.notifyAll(); } public synchronized void sub() throws InterruptedException { if (this.flag) { //现在进行的是减法操作,加法操作需要等待 super.wait(); } Thread.sleep(200); this.num--; System.out.println("[减法操作-" + Thread.currentThread().getName() + "]num = " + this.num + " " + this.flag); this.flag = true; super.notifyAll(); } } class AddThread implements Runnable { private Resource resource; public AddThread(Resource resource) { this.resource = resource; } @Override public void run() { for (int i = 0; i < 50; i++) { try { this.resource.add(); } catch (InterruptedException e) { e.printStackTrace(); } } } } class SubThread implements Runnable { private Resource resource; public SubThread(Resource resource) { this.resource = resource; } @Override public void run() { for (int i = 0; i < 50; i++) { try { this.resource.sub(); } catch (InterruptedException e) { e.printStackTrace(); } } } } public class MyCalculation { public static void main(String[] args) { Resource resource = new Resource(); AddThread addThread = new AddThread(resource); SubThread subThread = new SubThread(resource); new Thread(addThread, "加法线程A").start(); new Thread(addThread, "加法线程B").start(); new Thread(subThread, "减法线程A").start(); new Thread(subThread, "减法线程B").start(); } }
发现做最终运行结果如下:
[加法操作-加法线程A]num = 1 true
[减法操作-减法线程B]num = 0 false
[加法操作-加法线程B]num = 1 true
[减法操作-减法线程A]num = 0 false
[加法操作-加法线程A]num = 1 true
[减法操作-减法线程B]num = 0 false
[减法操作-减法线程A]num = -1 true
[加法操作-加法线程B]num = 0 true
[减法操作-减法线程A]num = -1 false
[减法操作-减法线程B]num = -2 true
[加法操作-加法线程A]num = -1 true
[减法操作-减法线程B]num = -2 false
[减法操作-减法线程A]num = -3 true
[加法操作-加法线程B]num = -2 true
[减法操作-减法线程A]num = -3 false
[减法操作-减法线程B]num = -4 true
[加法操作-加法线程A]num = -3 true
[减法操作-减法线程B]num = -4 false
[减法操作-减法线程A]num = -5 true
[加法操作-加法线程B]num = -4 true
[减法操作-减法线程A]num = -5 false
是什么原因会产生这样的现象呢?
因为楼主没有讲自己这段代码的具体用途,所以我假设 楼主的目的是想 实现:
"先增加,后减少,没有增加就不会减少,即 num不会出现负数的情况"。
我觉得这段代码是实现不了这样的需求的,原因如下:
【假设减的线程sub1进入,因为flag=true,所以wait(),放弃了对象锁,但是sub1已经进入了方法体。
这时候sub2进入,因为flag=true,所以也wait()了,也放弃了对象锁,但是sub2也已经进入了方法体。
这个时候 加的线程 add1 来了,没人拿锁,所以add1成功拿到,并且进入了方法体。num++;之后 flag=false; 此时num=1; 这时候add1执行 notifyAll();
sub1和sub2 都被唤醒了,此时他们都进入了方法体,所以两者都会成功 -1,于是sub1和sub2之后 num = -1;】
所以出现了楼主跑出来的结果。
明白了,主要就是因为wait()之后释放了锁,导致两个相同职责的线程有机会都进去这个方法,然后挂起等待,当执行NotifyAll()后,就会造成连续执行相同方法的情况。感谢指点