线程没有终止;陷入循环

Threads are not getting terminatedl; stuck in loop

我有 4 个线程,每个线程都在执行不同的方法,我能够提取所需的输出,但是线程没有终止或在作业完成后无法退出循环。

谁能帮我看看你的意见。

我认为每个线程都停留在 await 语句上并期待有人发出信号。我尝试在任务完成后显式地向所有线程发出信号,但没有成功。

当一个线程向其他线程发出信号时,执行线程不会重新检查 while 循环的条件,因为我将标志设置为 false 但它没有任何效果。

    private int n;
    Lock lock = new ReentrantLock();
    Condition executeFizz;
    Condition executeBuzz;
    Condition executeFizzBuzz;
    Condition executeNumber;
    volatile private boolean flag;   

    public FizzyBuzz(int n) {
        this.n = n;
        this.executeFizz = lock.newCondition();
        this.executeBuzz = lock.newCondition();
        this.executeFizzBuzz = lock.newCondition();
        this.executeNumber = lock.newCondition();
        this.flag = true;
    }

    public  void fizz()   {
        lock.lock();
        while(true) {
        try {           
            executeFizz.await();
            if(!flag) break;
        } catch (InterruptedException e) {
        }
        System.out.println("fizz");
        executeNumber.signal();
        }

    }

    public void buzz()  {
        lock.lock();
        while(true) {
        try {
            executeBuzz.await();
            if(!flag) break;
        } catch (InterruptedException e) {
        }
        System.out.println("buzz");
        executeNumber.signal();

        }

    }

    public void fizzbuzz()   {
        lock.lock();
        while(true) {
        try {
            executeFizzBuzz.await();
            if(!flag) break;
        } catch (InterruptedException e) {
        }
        System.out.println("fizzbuzz");
        executeNumber.signal();
        }

    }

    public  void number() throws InterruptedException  {
        lock.lock();
        for(int i=1;i<=n;i++)
        {       
            if(i%3==0&&i%5==0)
                {
                    executeFizzBuzz.signal();
                    executeNumber.await();
                }
            else if(i%3==0)
                {

                    executeFizz.signal();
                    executeNumber.await();
                }
                else if(i%5==0)
                {
                    executeBuzz.signal();
                    executeNumber.await();
                }
                else
                {
                    System.out.println(i);
                }   
        }
        flag = false;
        executeFizzBuzz.signal();
        executeFizz.signal();
        executeBuzz.signal();

也许这并不像您想象的那样:

while (flag) {
    ...
}

只要 flag 变为假,该循环将 不会 终止。它在 测试 flag 并发现它为假时终止。每次循环只发生一次。您可以改为这样编写循环,它的行为方式完全相同:

while (true) {
    if (! flag) break;
    ...
}

所以如果你有这个,

while (flag) {
    ...executeFizz.await()...
}

并且如果线程卡在 await() 调用中时 flag 从 true 变为 false,则循环不会终止,直到 after await() 调用 returns...

...这在您的示例中永远不会发生,因为在 for 循环计数到 n 后,它设置 flag=false; 但它不会 向任何其他等待线程发送信号。


@SolomonSlow i tried signalling all 3, but no luck after adding if condition, at the end of the code I included this code...

我的猜测是,这是因为您的程序中的任何地方都没有调用 lock.unlock()。以下是可能发生的情况:

  1. 三个 "worker" 线程都在调用 executeXxxxx.await()(每个都在等待自己的条件变量。)

  2. "main" 线程到达循环的末尾(它当前是 lock 的所有者)并且它向每个 executeXxxxxx 条件发出信号变量。

  3. "main"线程结束,但lock线程仍处于锁定状态。所有三个 "worker" 线程现在都已从等待它们各自的条件中释放出来,但是它们的 await() 调用不能 return 直到锁变得可用。

  4. 锁永远不会可用,因为没有 运行 线程可以解锁它。

您需要在每个线程结束前调用 lock.unlock()