【问题标题】:Alternative for volatiles with cheapest performance hit性能最便宜的挥发物的替代品
【发布时间】:2023-04-08 01:09:01
【问题描述】:

我想实现取消线程的常用协作机制。 但是,当我处于 JDK5 之前的环境中时,Java 内存模型仅在 JDK5 中得到修复。 我明白,这意味着像 SCIP 所支持的那样做这样的事情是不正确的。

class Worker implements Runnable
{
    private volatile boolean _canceled;

    public void cancel() { _canceled = true; }

    public void run() {
        while( ! _canceled )
        {
            // do my Stuff
        }
    }
}

我正在考虑使用 AtomicBoolean 来封装 _canceled 变量。 还有其他选择吗?

【问题讨论】:

  • 你的是一个布尔值。只有不稳定的多头/双打被打破,对吧?

标签: java multithreading concurrency


【解决方案1】:

AtomicBoolean 也在 JDK5 中添加,因此除非您使用 backport,否则此功能不可用。但是,是的,来自 backport 的 atomic 类可能是最好的选择,正如您所知,它是由精通每个版本的 JVM 虚拟机规范的人编写的。

【讨论】:

    【解决方案2】:

    如果我对FAQ 的理解正确,这在允许对易失性字段重新排序的旧内存模型中不是问题。在他们的示例中,旧模型将允许“x”基于 JVM 为 0 或 42。经验法则是,重新排序应该始终是编译器/cpu 的性能提升,但对程序员来说是不可见的。旧模型打破了这个规则。

    您的示例不应该遇到可见性问题并且可以工作

    【讨论】:

    • 我也是这么读的。如果示例中的 cancel() 方法在设置 _canceled 之前设置了一些其他(非易失性)字段,那么 run() 方法将无法保证在退出循环时看到该新值。但正如所写,这个例子可以工作。
    • 如果我告诉你我在 Java 1.1 中运行会怎样
    • 我会嘲笑你的痛苦,但我不会改变我的答案。见:books.google.com/…
    【解决方案3】:

    util.concurrent package by Doug Lea(java.util.concurrent 的前身)可能会有所帮助。

    【讨论】:

      【解决方案4】:

      IIRC,很老的 Sun JRE 根本没有实现 volatile。明智地尝试,旧的 JMM 允许以这种方式使用 volatiles(大约是它们可以使用的唯一方式)。我了解 Sun 1.4 JRE 实际上实现了 1.5 JMM,任何差异都被视为错误。

      【讨论】:

        【解决方案5】:

        我认为 AtomicBoolean 在 Java 5 之前也不可用。在私有布尔字段上同步怎么样?

        【讨论】:

        • 问题是问题的一部分:“最便宜的性能命中”。根据使用的 JDK5 之前的版本,同步可能会比较昂贵。
        猜你喜欢
        • 2018-06-27
        • 1970-01-01
        • 2010-09-09
        • 1970-01-01
        • 2013-02-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-22
        相关资源
        最近更新 更多