【问题标题】:Multiple threads reading a primitive type读取原始类型的多个线程
【发布时间】:2012-07-17 12:57:22
【问题描述】:

如果多个线程读取之前设置的原始类型并且以后不会更改,它们会得到错误的值吗?

例如,假设下面的简单代码摘录:

public static final boolean proceed = read(); // Read the value from a file

public static void doSomething() // Method accessed by multiple threads
{
    if (proceed)
    {
        System.out.println("TRUE");
    }
    else
    {
        System.out.println("FALSE");
    }
}

假设proceed变量初始化为true,是否有可能在同时运行doSomething()方法的多个线程中的一个或多个线程中,打印的消息是FALSE

如果proceed 变量是可变的,那肯定是可能的,因此需要同步,或使用AtomicBoolean(例如,根据this question)。但在这种情况下,proceed 是不可变的,并且只在包含类的静态初始化期间设置一次。

对于其他原始类型也是如此,如果一个值设置为 final,那么之后访问它应该始终是线程安全的,对吗?

【问题讨论】:

    标签: java thread-safety primitive


    【解决方案1】:

    由于 proceedstaticfinal ,它不能被重新分配,这变成了线程安全的。

    static 说它是类级别的,final 说它的值不能改变,这是一个 primitive,所以它绝对是不可变的,因此是线程安全的。

    【讨论】:

      【解决方案2】:

      引用是线程安全的,因为它是不可变的。

      如果它是可变的,则需要使用volatile 关键字来确保在另一个线程中修改时获得最新值。

      Do you ever use the volatile keyword in Java?

      【讨论】:

      • 虽然您对 double 和 long 的评论是准确的,但不适用于这个问题。使用双精度而不是布尔值的相同问题将得到相同的答案。
      【解决方案3】:

      您的变量是final 这一事实保证了所有线程都将看到它处于一致的初始化后状态。这也适用于对象的引用(即,如果对象已被初始化为非空引用,则所有线程都将看到该对象的非空值 - 但如果您的对象不是线程安全的,则某些线程可能会在不一致或陈旧的状态)。

      ps:这是假设您的 read 方法不尝试读取布尔值,在这种情况下它会看到默认 (false) 值。

      【讨论】:

        【解决方案4】:

        你说它是不可变的(static and final),所以我们可以肯定地说它是线程安全的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-10-21
          • 2015-06-16
          • 1970-01-01
          • 2017-05-27
          • 1970-01-01
          • 1970-01-01
          • 2015-03-18
          相关资源
          最近更新 更多