无法使notifyAll按预期工作

时间:2016-04-29 02:59:24

标签: java

我在Runnable类A中有一个函数:

public void function1(){
     synchronized(lock){
        function2.decrease();
        lock.notifyAll();
        System.out.print(function2.getValue());
}

我在Runnable类B中有另一个函数:

public void function3(){
    try{
        synchronized(lock){
            while(!(function2.getValue() != 0)){
                lock.wait();
            }
            Thread.sleep(1000);
            System.out.println(function2.getValue() + 10);
        }
    }catch(InterruptedException e){
        System.err.println(e);
    }
}

当我运行程序时,即使等待条件的计算结果为true,它也会在function3中打印之前打印在function1中。

在function1中打印值之前,我需要做什么才能在function3中打印值?

1 个答案:

答案 0 :(得分:1)

看起来你可能多次运行function1来减少function2的值,然后在function3中执行while循环检查。因此,首先,在这种情况下期望function1在function3之前打印是完全正常的,因为function3在其print语句之前等待1秒,而在此期间function1可以做任何想做的事情。

其次,或许更优雅的解决方案是在function1中检查function2的值,然后在== 0的情况下检查notifyAll()。这样,在function3中不需要while循环,它只是使用wait ()并等待来自function1的notifyAll()调用。

我的意思是: Function1 add

if(function2.getValue() == 0)
    lock.notifyAll();

Function3删除while循环

// no while loop
lock.wait();

然后回答原始问题,确保function3首先在function1中的if语句中打印,在notifyAll()之后调用lock.wait()并在function3结束时添加notifyAll()。

下面的Compilable类演示了。

public class StackSyncProb{
    private volatile int function2;
    private Object lock = new Object();

    public static void main(String[] args){
        StackSyncProb s = new StackSyncProb(3); // function2 starts at 3
        // start function3, which waits
        s.runFunction3();
        // decrement using function1 until hit 0 (in this case, 3 times)
        for(int i = 0; i < 3; i++){
            s.runFunction1();
        }
    }

    public StackSyncProb(int v){
        function2 = v;
    }

    public void runFunction1(){
        new Thread(new Run1()).start();
    }

    public void runFunction3(){
        new Thread(new Run2()).start();
    }

    public class Run1 implements Runnable{
        @Override
        public void run(){
            function1();
        }
        public void function1(){
            try{
            synchronized(lock){
                function2--;
                // Use if statement to check inside function1 instead of in function3
                if(function2 == 0){
                    lock.notifyAll();
                    // After notifying, wait until function3 done
                    lock.wait();
                }
                System.out.println("function1: " + function2);
            }
            }catch(InterruptedException e){}
        }
    }

    public class Run2 implements Runnable{
        @Override
        public void run(){
            function3();
        }
        public void function3(){
            try{
                synchronized(lock){
                    // No while loop
                    lock.wait();
                    Thread.sleep(1000);
                    System.out.println("function3: " + (function2 + 10));
                    // Notify function1 it can complete and print
                    lock.notifyAll();
                }
            }catch(InterruptedException e){
                System.err.println(e);
            }
        }
    }
}