什么是原子?

时间:2011-11-10 07:34:20

标签: java terminology atomicity

这是两个原子操作:

int value = 5;
Object obj = new Object();

但是当使用原语作为方法参数时,这会被视为原子操作: public void setValue(int val, Object obj){
this.value = val; // Atomic?
this.obj = obj; // Not atomic?
}

? 对象引用的副本不是原子的,因为它包含一个read和write,对吗?

说对象引用进行原子操作的唯一方法是将其声明为null或为其分配新对象,如:

是否正确?
Object obj = null;

Object obj = new Object();

4 个答案:

答案 0 :(得分:4)

  

如果上述方法中的参数是对象的引用,   然后操作不会是原子的,对吧?

一般来说,这是正确的。一个好的经验法则是考虑根本没有原子性,即使是像以下原语:

int b,c; 
int a = ++b - c;

只有原语,但整个分配可能不是原子的。

如果您需要原子操作,那么您有不同的可能性:

  • synchronized blocks
  • 不可变对象
  • 特定库(java.util.concurrent.atomic)

答案 1 :(得分:3)

当一个线程读取一个原语(long和double除外)或一个对象引用的值时,它会看到它在这个变量中设置的值,或者另一个线程在这个变量中设置的值。

但是,虽然在一个线程中为共享变量赋值是原子的,但这并不意味着所有其他线程都会立即看到新值。为此,应将变量声明为volatile。 volatile也会写入长双原子。在这种情况下,我更喜欢使用AtomicXxx(AtomicLong,AtomicBoolean等)。

如果你想原子地改变两个共享变量的值,那么你应该使用一个独特的锁同步每个访问(读和写)这些变量。

此外,每个“check then act”或“read then write”操作都是非原子的。这意味着这些操作也需要同步:

a++; // read a, increment value, write value to a
if (a > 0) {a = b;} // check value of a, then assign new value to a.

你问题中的每一个操作都是原子的。但是在setValue()中,你有两个原子操作。整个setValue调用不是原子的。

答案 2 :(得分:1)

To the JLS!

  

当线程使用变量的值时,它获得的值实际上是由该线程或某个其他线程存储到变量中的值。即使程序不包含正确同步的代码,也是如此。例如,如果两个线程将对不同对象的引用存储到同一个引用值中,则该变量随后将包含对一个对象或另一个对象的引用,而不是对某个其他对象的引用或损坏的引用值。

所以赋值是原子的。

答案 3 :(得分:0)

public synchronized void setValue(int val, Object obj)

现在整个函数都是“原子”,我在Java中没有看到这个术语