Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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原子操作_Java_Multithreading_Atomic - Fatal编程技术网

java原子操作

java原子操作,java,multithreading,atomic,Java,Multithreading,Atomic,将以下语句分开是正确的: int v = ++j; 作为: 读取j值(原子) 将读取的值增加1(非 原子干涉 其他线程) 将加法结果写入i (原子的) 将i写入v(原子) 我会用 带有的快速视图显示以下说明字节码: int j = 0; // 0 0:iconst_0 // 1 1:istore_1 int v = ++j; // 2 2:iinc 1 1 // 3 5:iload_1 // 4

将以下语句分开是正确的:

int v = ++j;
作为:

  • 读取j值(原子)
  • 将读取的值增加1(非 原子干涉 其他线程)
  • 将加法结果写入i (原子的)
  • 将i写入v(原子)
  • 我会用

    带有的快速视图显示以下说明字节码:

        int j = 0;
    //    0    0:iconst_0
    //    1    1:istore_1
        int v = ++j;
    //    2    2:iinc            1  1
    //    3    5:iload_1
    //    4    6:istore_2
    

    接近。第二步是原子的。在这种情况下,
    j
    必须是
    byte
    char
    short
    int
    中的一个,并且可以自动加载和存储其中的每一个

    一旦一个值被加载到硬件寄存器中,另一个线程就不可能干扰它。JLS中可能有一些关于原始操作的原子性。。。但是我看不出来。

    是的,
    int
    (或更小的数据类型)读/写/算术运算是原子的。引用(读/写)也是原子的,不管它是32位还是64位

    但是,对64位
    long
    double
    的操作可能不是原子操作

    一些实现可能会发现将64位
    值上的单个写入操作划分为相邻32位值上的两个写入操作很方便。为了提高效率,这种行为是特定于实现的;Java虚拟机可以对
    long
    double
    值执行原子写入或分两部分写入

    对于Java编程语言内存模型,对非易失性
    或双值的单次写入被视为两次单独的写入:每32位的一半写入一次。这可能导致线程在一次写入中看到64位值的前32位,在另一次写入中看到第二个32位。写入和读取
    volatile long
    double
    值始终是原子的。对引用的写入和读取始终是原子的,不管它们是作为32位还是64位值实现的

    鼓励VM实现者尽可能避免拆分其64位值。鼓励程序员将共享的64位值声明为
    volatile
    ,或者正确地同步他们的程序,以避免可能的复杂性

    请注意,无论是增量/减量之前还是之后的运算符本身都不是原子的,甚至在
    int
    byte
    上也不是原子的:读/写/算术运算在明显不同的步骤中发生

    另见

    • 是的,你的假设是正确的。递增一个int会导致三个步骤(因此它不是原子的),分配它是另一个步骤。下面是生成的字节码:

      ..
      istore_1
      iinc    1, 1
      iload_1
      istore_2
      ..
      

      这个问题的目的是什么?了解编译器生成的字节码是什么?要了解如何使此线程安全?只需知道非读/写操作是否为原子操作即可。查看操作列表:;对于内存模型来说,数字相加是否是原子的并不重要。重要的是读/写。Java语言没有读-修改-写作为一个原子操作。还要注意,
      v
      不是易变的,因此不能保证其他读取线程会看到对它的写入。是的,谢谢,但我只想知道JVM是否像我写的那样分割上述操作。或者
      double
      。(而不是
      volatile
      )在示例代码中,它不能是
      long
      double
      。步骤2是原子的吗?为什么?在许多书中,我读到只有读/写操作是原子的@xdevel2000回顾(当前)问题步骤1和3可能会使用不同的数据类型。@xdevel2000:在步骤2中,加载的值是递增的。它是原子的(或者可能这里不适用原子这个术语),因为加载的值是线程的本地值,所以没有其他人可以修改它。(但是另一个线程可能在第一个线程执行写操作之前执行读操作,因此增量可能仍然会被跳过)另请参见JLS保证防止单词撕裂谢谢,但是我真的不明白步骤2是否是原子的。斯蒂芬说“是”,而你和其他人似乎说“不是”。我很困惑。我的be i++作为一个整体被认为不是原子的,而所有被划分的子操作都是原子的(包括增量)??@xdevel2000:真正重要的是读写的原子性<代码>i++可能由原子读取和原子写入组成,但作为一个整体,不是一个原子“读-加-写”操作。
      ..
      istore_1
      iinc    1, 1
      iload_1
      istore_2
      ..