java原子操作

时间:2010-08-10 14:04:28

标签: java multithreading atomic

将以下陈述分开是正确的:

int v = ++j;

为:

  1. 读取j值(原子);
  2. 将读取的值增加1(NON 原子可能干扰 其他线程);
  3. 将添加结果写入i (原子);
  4. 将我写入v(原子)

4 个答案:

答案 0 :(得分:8)

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

但是,对64位longdouble的操作可能不是原子操作。

JLS 17.7 Non-atomic Treatment of double and long

  

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

     

出于Java编程语言内存模型的目的,对非volatile longdouble值的单个写入被视为两个单独的写入:每个写入一个32-一点半。这可能导致线程从一次写入看到64位值的前32位,而从另一次写入看到第二次32位的情况。 volatile longdouble值的写入和读取始终是原子的。对引用的写入和读取始终是原子的,无论它们是实现为32位还是64位值。

     

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

请注意,前置或后置递增/递减运算符本身都不是原子的,甚至不在intbyte上:读/写/算术运算在明显不同的步骤中发生。

另见

答案 1 :(得分:1)

关闭。第2步是原子的。在这种情况下,j必须是bytecharshortint中的一个,并且每个都可以加载并以原子方式存储。

一旦将值加载到硬件寄存器中,其他线程就不可能干扰它。在JLS中可能存在关于原始操作的原子性的东西......但我无法发现它。

答案 2 :(得分:1)

是的,你的假设是正确的。增加一个int导致三个步骤(因此它不是原子的),分配它是另一个步骤。这是结果字节码:

..
istore_1
iinc    1, 1
iload_1
istore_2
..

答案 3 :(得分:0)

我会使用AtomicInteger

AtomicInteger j; // do init

int v = j.incrementAndGet();

JAD的快速视图显示了以下字节代码:

    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