java - java变量本身线程安全吗?什么时候更新变量?

标签 java multithreading synchronization thread-safety volatile

假设我有两个线程更新一个对象,一个线程在没有同步的情况下从该对象读取。显然,这是运行状态。但是,我想知道变量本身是否只能部分写入。

public class CommonObject extends Object
{
    static int memberVar=-1;
}

public class Input1Thread extends Thread
{   
    public void run()   
    {
        while(true)
            CommonObject.memberVar = 1
    }
}

public class Input2Thread extends Thread
{   
    public void run()   
    {
        while(true)
            CommonObject.memberVar = 2;
    }
}

public class OutputThread extends Thread
{   
    public void run()   
    {
        while(true)
            System.out.println("CommonObject.memberVar"+ CommonObject.memberVar);
    }
}  

我假设打印出来的值也将是 2 或 1。但是,我想知道该变量是否可能已设置一半?

我使用基元作为示例,但我希望对象的答案也适用,如果它不同的话。

最佳答案

这取决于变量的类型。

doublelong(Java 中的两种 64 位类型)如果不是 volatile 则允许进行字撕裂>,而所有其他类型(包括引用)可能永远不会撕裂。字撕裂会给您带来您担心的行为:一些字节来自旧值,其中一些来自新值,总体结果是一个既不是旧值也不是新值的值。

这在 JLS 17.7 中指定:

For the purposes of the Java programming language memory model, a single write to a non-volatile long or double value is treated as two separate writes: one to each 32-bit half. This can result in a situation where a thread sees the first 32 bits of a 64-bit value from one write, and the second 32 bits from another write.

Writes and reads of volatile long and double values are always atomic.

Writes to and reads of references are always atomic, regardless of whether they are implemented as 32-bit or 64-bit values.

当然,引入数据竞争会带来一系列问题;但你的问题是专门针对文字撕裂的,所以我只是在这里解决这个问题,只是要注意“仅仅因为你可以,并不意味着你应该”。您应该小心地分析您拥有的每个数据竞争,并证明它是良性的(正如其中一些数据竞争一样,例如 String.hashCode 对其值的缓存)。

关于java - java变量本身线程安全吗?什么时候更新变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35691904/

相关文章:

c++ - 为什么没有像 pthread_mutex_t & std::mutex 那样的 std::等价于 pthread_spinlock_t?

android - 将 ParseObject 与 Parse.com 同步的最有效方法

java - 不使用 cookie 的 Spring Security session

java - java中同步块(synchronized block)之后的代码

java - 将 JSON 导入 Netbeans 项目

javascript - XPCOM C++多线程和javascript回调

java - 没有打印语句,循环看不到其他线程更改的值

iphone - 如何在 Iphone native 应用程序中同步 Google 日历、雅虎日历和 Toodledo?

java - jdb 调试时烦人的包名

java - 在 JBoss 中保护 REST API