notifyAll()不起作用

时间:2015-09-10 07:49:52

标签: java multithreading concurrency wait

在以下代码中,调用notifyAll()但不重新激活其他线程。我得到的输出是

  • 测试版等待及时通知:1441870698303,activeWriters:1

  • alpha等待及时收到通知:1441870698303,activeWriters:1

  • delta通知所有时间:1441870698403,activeWriters:0

    public class Waiter实现了Runnable {

        private static int activeWriters;
    
        public Waiter(Message msg){
        }
    
        @Override
        public void run() {
            beforeWrite();
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            afterWrite();
        }
    
        protected synchronized void beforeWrite(){
            while (activeWriters > 0 ) {
                try {
                    System.out.println(Thread.currentThread().getName() +" waiting to get notified at time: "+System.currentTimeMillis()+ ", activeWriters: " + activeWriters);
                    wait();
                    System.out.println(Thread.currentThread().getName() +" waiting got notified at time: "+System.currentTimeMillis()+ ", activeWriters: " + activeWriters);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            ++activeWriters;
        }
        protected synchronized void afterWrite(){
            --activeWriters;
            System.out.println(Thread.currentThread().getName() +" notify all at time: "+System.currentTimeMillis() + ", activeWriters: " + activeWriters);
            notifyAll();
        }
    
    }
    
    public class WaitNotifyTest {
    
        public static void main(String[] args) {
            Message msg = new Message("process it");
            Waiter waiter1 = new Waiter(msg);
            Waiter waiter2 = new Waiter(msg);
            Waiter waiter3 = new Waiter(msg);
            new Thread(waiter1,"alpha").start();
            new Thread(waiter2, "beta").start();
            new Thread(waiter3, "delta").start();
    
        }
    
    }
    

2 个答案:

答案 0 :(得分:4)

调用wait()notify*()处理指定的对象,这意味着notify*()唤醒在同一对象上调用wait()的线程。

在您的情况下,您在3个未连接的对象上拨打wait()notifyAll(),这样就无法使用。

您可以添加静态互斥锁:

private static final Object mutex = new Object();

然后在此对象上调用wait()notify*()。记住首先在互斥锁上同步:

synchronized (mutex) {
    ...
    mutex.wait();
    ...
}

synchronized (mutex) {
    ...
    mutex.notifyAll();
    ...
}

由于两个原因,对activeWriters块的所有访问都必须位于这些synchronized块中。目前对它的访问实际上是不同步的,因为您在3个不同的对象上进行同步。除了activeWriters是你的条件变量,你想要notify*()其他线程改变它。为此,变量和notify*()调用的更改必须位于同一synchronized块中。

答案 1 :(得分:0)

您的计划存在重大设计缺陷。

您正在创建3个单独的Waiter类实例,并期望它们以同步方式访问activeWriters。这是不可能的,因为实例方法将获取不同的锁,但修改相同的静态变量activeWriters

要提供静态变量并发访问,您应该通过它来访问它们。同步静态方法。 一种方法是制作beforeWrite()afterWrite()方法static