java变量本身是否安全?更新变量时? [英] Are java variables themselves thread safe? When updating variables?

查看:177
本文介绍了java变量本身是否安全?更新变量时?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Suppose I have two threads updating an object, and one thread reading from that object with no synchronization. Obviously, this is run condition. However, I am wondering if the variable itself can only partially written.

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.但是,我想知道变量是否可能在中途设置?

I would assume the value printed out will also be either 2 or 1. However, I was wondering if it was possible that the variable might be halfway set?

我用原语作为例子,但我想答案是对于对象,如果它不同。

I used primitives as an example, but I would like the answer would for objects also, if it is different.

推荐答案

这取决于变量的类型。

double s和 long s(Java中的两个64位类型)是如果它们不是 volatile ,则允许破解,而所有其他类型(包括引用)可能永远不会撕裂。单词撕裂会给你你担心的行为:一些字节来自旧值,其中一些来自新值,整体结果是一个既不旧又不新的值。

doubles and longs (the two 64-bit types in Java) are allowed to word-tear if they're not volatile, while all other types (including references) may never tear. Word tearing would give you the behavior you're worried about: some of the bytes are from the old value, some of them are from the new value, and the overall result is a value that's neither the old nor new.

这是在 JLS 17.7


出于Java编程语言内存模型的目的,单个写入非易失性long或double值被视为两个单独的写入:每个32位半写一个。这可能导致线程从一次写入看到64位值的前32位,而从另一次写入看到第二位32位。

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.

写入和读取volatile和double值总是原子的。

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

写入和读取引用始终是原子的,无论它们是以32位还是64位实现价值。

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

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

Of course, introducing data races introduces a whole host of issues; but your question was specifically targeted at word tearing, so I'm only addressing that here, except to note that "just because you can, doesn't mean you should." You should be careful to analyze each data race you have and prove that it's benign (as some of them are -- like String.hashCode's caching of its values).

这篇关于java变量本身是否安全?更新变量时?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆