Java 我的线程没有';我得不到通知,我的程序挂起

Java 我的线程没有';我得不到通知,我的程序挂起,java,multithreading,synchronization,java-threads,Java,Multithreading,Synchronization,Java Threads,下面的代码没有得到通知线程读取器它执行writer然后终止。为什么会这样?notifyall应该唤醒所有处于等待状态的线程 public class Testing { public static void main(String[] args) { Testing testing=new Testing(); testing.reader.start(); testing.writer.start(); } Thread

下面的代码没有得到通知线程读取器它执行writer然后终止。为什么会这样?notifyall应该唤醒所有处于等待状态的线程

public class Testing {

    public static void main(String[] args) {
        Testing testing=new Testing();
        testing.reader.start();
        testing.writer.start();
    }
    Thread reader = new Thread("reader") {
        public void run() {

            System.out.println("reader started");

            synchronized (this) {
                try {

                    wait();
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
            for (int i = 0; i < 10; i++) {
                System.out.println("reader " + i);

            }
        }

    };
    Thread writer = new Thread("writer") {
        public void run() {
            System.out.println("writer started");

            for (int i = 0; i < 10; i++) {
                System.out.println("writer " + i);
            }
             synchronized (Thread.currentThread()) {
                 notifyAll();
            }

        }

    };

}
公共类测试{
公共静态void main(字符串[]args){
测试=新测试();
testing.reader.start();
testing.writer.start();
}
线程读取器=新线程(“读取器”){
公开募捐{
System.out.println(“读卡器已启动”);
已同步(此){
试一试{
等待();
}捕获(中断异常例外){
例如printStackTrace();
}
}
对于(int i=0;i<10;i++){
System.out.println(“读卡器”+i);
}
}
};
线程编写器=新线程(“编写器”){
公开募捐{
System.out.println(“编写器启动”);
对于(int i=0;i<10;i++){
System.out.println(“writer”+i);
}
已同步(Thread.currentThread()){
notifyAll();
}
}
};
}
NotifyAll()不属于Thread类,而是属于Object基类;在Thread writer中,NotifyAll()是writer Object的函数,可以
唤醒具有writer对象锁的线程;

下面的代码没有得到通知线程读取器它执行writer然后终止。为什么会这样

您的程序未完成,因为写入线程终止,但读取器线程卡在
wait()
中。代码的问题是读线程正在等待它自己的线程对象,而写线程正在通知它自己的线程对象,这是不同的。您需要做的是让它们在同一个对象实例上等待并通知

快速修复方法是使用静态锁定对象:

private static final Object lockObject = new Object();
// reader:
synchronized (lockObject) {
    lockObject.wait();
...
// writer
synchronized (lockObject) {
    lockObject.notify();
然后读写器都在锁定、等待和通知同一个最终对象实例。在无法更改的字段上进行同步是一种很好的模式,因此
private final Object
或类似的字段是最好的。另外,您只有一个线程,因此
notify()
就足够了

但是,您的代码仍然存在争用条件问题。在读取器到达
wait()
之前,您的编写器可以调用
notifyAll()
(尽管可能性不大)。如果通知发生,并且没有人等待,那么这是一个noop,读卡器在到达
wait()
时将挂起

更好的解决方案是使用共享的
AtomicBoolean

private final AtomicBoolean writerDone = new AtomicBoolean();
...
// reader
while (!writerDone.get()) {
    synchronized (writerDone) {
        writerDone.wait();
    }
}
// writer
writerDone.set(true);
synchronized (writerDone) {
    writerDone.notifyAll();
}

您只需做少量更改,如下所示:

public static void threadTest(){
        Test testing = new Test();
        testing.lock = new Object();
        testing.reader.start();
        testing.writer.start();
    }
    private  Object lock;
    Thread reader = new Thread("reader") {
        public void run() {

            System.out.println("reader started");

            synchronized (lock) {
                try {
                    lock.wait();
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
            for (int i = 0; i < 10; i++) {
                System.out.println("reader " + i);

            }
        }

    };
    Thread writer = new Thread("writer") {
        public void run() {
            System.out.println("writer started");

            for (int i = 0; i < 10; i++) {
                System.out.println("writer " + i);
            }
            synchronized (lock) {
                lock.notifyAll();
            }

        }

    };
publicstaticvoidthreadtest(){
测试=新测试();
testing.lock=新对象();
testing.reader.start();
testing.writer.start();
}
私有对象锁;
线程读取器=新线程(“读取器”){
公开募捐{
System.out.println(“读卡器已启动”);
已同步(锁定){
试一试{
lock.wait();
}捕获(中断异常例外){
例如printStackTrace();
}
}
对于(int i=0;i<10;i++){
System.out.println(“读卡器”+i);
}
}
};
线程编写器=新线程(“编写器”){
公开募捐{
System.out.println(“编写器启动”);
对于(int i=0;i<10;i++){
System.out.println(“writer”+i);
}
已同步(锁定){
lock.notifyAll();
}
}
};

yes调用当前线程时返回读线程。但是notify和notifyall都不会唤醒等待的线程。oops!这是一个错误。我将向writer更正。实际上,现在返回的当前线程是writer。您能否帮助我了解如何通知读线程。在未事先确认
synchronized
块内您等待的事情尚未发生之前,请不要调用
wait
。在调用
wait
后,在未确认等待的事情已经发生之前,不要离开
synchronized
块。(此外,编写器调用
notifyAll
,而没有更改
synchronized
块中的任何内容,因此没有任何需要通知的内容。)