【问题标题】:Using synchronized block to protect against infinite loops使用同步块来防止无限循环
【发布时间】:2016-02-05 23:51:11
【问题描述】:

我目前正在开发一个应用程序,该应用程序在某些测试用例中会进入无限循环,但如果我重做相同的测试,它会运行良好。为了防止它发生,我使用辅助线程来监控自任务开始以来经过的时间,但我目前没有使用同步块,因为我不知道如何使用。

这是一个例子:

public class ThreadHarvest {
    private static final ReentrantLock lock = new ReentrantLock();
    private static boolean safe;

    public static void main(String[] args) throws InterruptedException
    {
        Thread task = new Thread(() ->{
            lock.lock();
            safe = false;

            for (long i = 10000000L; i > 0L; --i)
                System.out.println(i);

            safe = true;
            lock.unlock();

            System.out.println("Safe ended!");
        });

        task.start();

        while (lock.isLocked() == false);

        lock.tryLock(5, TimeUnit.SECONDS);

        if (!safe)
        {
            task.stop();
            System.out.println("Force ended!");
        }
    }
}

另外,还有一个特定的区域可以保证是安全的,就是在锁被释放之后。而且我也知道 stop 方法已被弃用,所以如果你碰巧有一些好主意来减少出错的可能性,我将非常感谢:D

【问题讨论】:

  • 注意:由于boolean safe 不是易失性的,您的主线程可能看不到这种变化。
  • 同步不是对无限循环的防御,但它是一种将它们转换为死锁的可能方法。你的问题没有意义。
  • @PeterLawrey iirc, ReentrantLock 还要确保更改可见。 (你可以用谷歌搜索java reentrantlock memory barrier)。 OP 使用它的方式似乎工作正常(需要更多检查:P)
  • OP:afaik,Java 中没有适当的方法来“强制”结束线程。您可能想通过 Google 搜索 Java thread interrupt 来搜索如何处理类似情况。简而言之,你的线程应该被重写以准备中断,你的主线程中断相应的线程以试图阻止它们继续工作。

标签: java parallel-processing synchronized locks


【解决方案1】:

我不太明白你的问题,但这里有一些关于你的代码的通用 cmets。

  • 你不应该有这样的旋转循环。我会添加 Thread.sleep(10); 或其他内容。
  • 使用锁时,您应该始终将解锁放在lock; try { } finally { unlock; } 中。然后你知道你的锁即使抛出异常也会被解锁。
  • 如果您在两个不同的线程中访问一个字段,您必须以某种方式保护它。您可以将AtomicBoolean 用于safe 或将其标记为volatile boolean,否则主线程可能看不到任何更改。无法保证与 isLocked()tryLock() 的内存同步。
  • 与其锁和保险箱,不如尝试做一个task.join(5, TimeUnit.SECONDS),然后测试if (task.isAlive()) { killItWithFire(); }

我目前正在开发一个在某些测试用例中进入无限循环的应用,

在我看来,您应该集中精力解决这个问题。 thread.stop() 是一个真正的黑客。

【讨论】:

  • 一种意见:应该改为lock; try {...} finally {unlock;}。如果锁定发生任何错误,您不想解锁
  • 另一件事是,我怀疑这里是否需要使用AtomicBooleanvolatileReentrantLock 也用于内存屏障的目的(就像synchronized
  • 锁好@AdrianShum。固定的。 Safe 可以设置为 true before !safe 测试可能没问题,但我宁愿安全,特别是因为 tryLock(...) 不保证根据文档的内存同步,除非它成功。
  • @Gary 哦,你是对的。我原本以为!safe检查的最后一部分发生在tryLock成功之后
猜你喜欢
  • 2021-01-16
  • 2012-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多