首页 > 解决方案 > 线程没有被终止;陷入循环

问题描述

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

有人可以帮我谈谈你的意见。

我认为每个线程都坚持等待声明并期待有人发出信号。我尝试在任务完成后明确地向所有线程发出信号,但没有运气。

当一个线程向其他线程发出信号时,执行线程不会重新检查 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();

标签: javamultithreadingconcurrencysynchronizationlocking

解决方案


也许这不会像你想象的那样做:

while (flag) {
    ...
}

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

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

所以如果你有这个,

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

如果flag线程卡在调用中时从 true 更改为 false await(),则循环不会终止,直到调用返回await()......

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


@SolomonSlow 我尝试向所有 3 个信号发送信号,但在添加 if 条件后没有运气,在代码的末尾我包含了此代码...

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

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

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

  3. “主”线程结束,但lock仍被锁定。现在,所有三个“工作”线程都已从等待各自条件的状态中释放出来,但await()在锁可用之前,它们的调用无法返回。

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

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


推荐阅读