LeetCode 1116 Java并发问题,等待线程会重新访问之前的代码吗?

问题描述 投票:0回答:1

这是我解决问题的代码,工作正常,但是,当我在同步语句下更改 while 语句时,似乎任何在notifyall()之后获得锁的线程都会继续运行代码并导致奇数方法接受偶数,偶数方法接受奇数。

class ZeroEvenOdd {
    private int n;
    private AtomicInteger counter;
    private AtomicInteger mode;
    private Object lock;
    
    public ZeroEvenOdd(int n) {
        this.n = n;
        this.counter = new AtomicInteger(0);
        this.mode = new AtomicInteger(0);
        this.lock = new Object();

    }

    public void zero(IntConsumer printNumber) throws InterruptedException {
        while(counter.get() < n){
            synchronized(lock){
                // if I change this line to 
                // if(mode.get() == 1 || mode.get() == 3){lock.wait();}
                // then everything goes wrong
                while(mode.get() == 1 || mode.get() == 3){lock.wait();}

                if(counter.get() < n){
                    printNumber.accept(0);}
                    mode.incrementAndGet();
                    lock.notifyAll();
            }
        }
    }

    public void even(IntConsumer printNumber) throws InterruptedException {
        while(counter.get() < n){
            synchronized(lock){
                 // if I change this line to 
                // if(mode.get() != 3){lock.wait();}
                // then everything goes wrong
                while(mode.get() != 3){lock.wait();}
                if(counter.get() < n){
                    printNumber.accept(counter.incrementAndGet());}
                mode.set(0);
                lock.notifyAll();
            }
            
        }
        
    }

    public void odd(IntConsumer printNumber) throws InterruptedException {
        while(counter.get() < n){
            synchronized(lock){
                 // if I change this line to 
                // if(mode.get() != 1){lock.wait();}
                // then everything goes wrong
                while(mode.get() != 1){lock.wait();}
                if(counter.get() < n){
                    printNumber.accept(counter.incrementAndGet());}
                mode.incrementAndGet();
                lock.notifyAll();
                
            }

        }
        
    }
}

在我看来,当我使用while时,无论哪个线程在notifyAll之后获得锁,都会再次检查模式,但是当我更改为if时,它不会检查模式,只是从离开的地方继续。

网上查了一下,notifyAll()之后,下一个获得锁的线程会从原来的地方继续,不会再去访问wait()之前的代码。

但是通过在这里使用 while ,它会奇怪地再次检查模式变量。

java wait synchronized java.util.concurrent notify
1个回答
0
投票

while
是一个循环结构。

线程并不是重新访问之前的代码 - 它只是再次循环:

while (mode.get() != 1) {
    lock.wait();
}

wait()
调用完成后,循环条件将以与

相同的方式再次评估
while (counter.get() < n) {
    // some code here that might modify the value of the counter
}
只要

counter.get()

 返回的值小于 
n
就会循环。

另一种方法(使用 if):

if (mode.get() != 3) {
    lock.wait();
}
如果

lock.wait();

 返回其他内容,然后 
mode.get()
仅调用
3
一次。
lock.wait();
返回后,它只会继续执行
if
语句之后的代码,无论
mode.get()
会返回什么。

© www.soinside.com 2019 - 2024. All rights reserved.