Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/377.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java:同时使用两个线程更改/替换和读取相同的int/对象安全吗?_Java_Multithreading - Fatal编程技术网

Java:同时使用两个线程更改/替换和读取相同的int/对象安全吗?

Java:同时使用两个线程更改/替换和读取相同的int/对象安全吗?,java,multithreading,Java,Multithreading,例如,有两个线程:一个线程读取int,另一个线程更改int值 这些线程是否安全,不受内存损坏和其他危险因素的影响?第一个线程是否会成功地将整数写入变量,第二个线程是否会成功地读取变量而没有任何问题 物体也是这样吗?当另一个线程重复读取对象引用时,用另一个对象替换对象引用是否安全 编辑:第二个线程将只读取它,当一个线程写入另一个线程读取时,它不会更改变量,应该没有问题,但是如果整数的值很重要,它将生成一个竞争条件。在这种情况下,使用:AtomicInteger和/或java中的锁。这将防止比赛状态

例如,有两个线程:一个线程读取int,另一个线程更改int值

这些线程是否安全,不受内存损坏和其他危险因素的影响?第一个线程是否会成功地将整数写入变量,第二个线程是否会成功地读取变量而没有任何问题

物体也是这样吗?当另一个线程重复读取对象引用时,用另一个对象替换对象引用是否安全


编辑:第二个线程将只读取它,当一个线程写入另一个线程读取时,它不会更改变量,应该没有问题,但是如果整数的值很重要,它将生成一个竞争条件。在这种情况下,使用:AtomicInteger和/或java中的锁。这将防止比赛状态

原子整数


是的,这是安全的,因为您永远不会遇到半更新的int变量,它将包含旧值或新值,但不会混合使用它们的字节。虽然JLS,第17章完全不是一本有趣的读物,而且都包含相同的神秘词,但这是本主题中提供的最好的内容,尽管后来它建议Java内存模型确保的不是这种顺序一致性:

在顺序一致的执行中,所有单独的操作(如读写)都有一个总的顺序,这与程序的顺序一致,并且每个单独的操作都是原子的,每个线程都可以立即看到

最后有一些相反的建议,其中任何一个:

17.7。双金属和长金属的非原子处理 对于Java编程语言内存模型而言,对非易失性长或双值的单次写入被视为两次单独的写入:每32位半写一次。这可能导致线程在一次写入中看到64位值的前32位,在另一次写入中看到第二个32位

因此,这两种64位类型可能不是非原子的,尽管这里没有引用它们也是原子的

对于对象引用的特定情况,毫无疑问:

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

上的建议或其源更像是一个易失性整数,包含来自内部sun.misc.Unsafe类的额外操作—大多数xAndY方法。与赤脚实现相比,它具有更高的性能

顺便说一句:Java中有一个volatile关键字,当您希望在所有平台上看到来自另一个线程的更新在一个线程中发生时,应该使用这个关键字

老实说,这个奇怪的测试在Windows上对我有效,即使没有volatile:


不,不是。有一个AtomicInteger类你可以使用,读写它们本身从来都不是问题。当您有依赖项时,问题就会出现。例如,一个线程根据该值进行读取和写入,例如i++。i++具有读写依赖性,如果在读取之后、写入之前和另一个线程修改之前被中断,则会得到意外的结果。@Zabuza没有顺序,对我来说最重要的是,当它结束写入变量并暂停时,另一个线程会正确读取最后一个变量。基本上不会。当两个线程之间有共享内存访问时,您需要同步。无论是锁、原子、记忆障碍,都取决于代码。但是您需要一些东西,否则您将进入数据竞争、竞争条件等。您应该展示您的代码并解释期望的结果。没有它很难得到确切的条件。
static volatile int c=0;
public static void main(String[] args) {
    Thread t=new Thread(new Runnable() {
        @Override
        public void run() {
            while(!Thread.interrupted())
                c=(c+1)%3;
        }
    });
    t.start();
    int some=10;
    while(some>0)
        if(c==0 && c==1 && c==2){
            System.out.println("Bingo!");
            some--;
        }
    t.interrupt();
}