开发者

Method call and atomicity

I have a method开发者_运维问答 with a single atomic operation, like this one

int value;

public void setValue(int value) {
    this.value = value;
}

then I call it in obvious way, like

foo.setValue(10);

The question is: would it be atomic operation? If no, what atomic operations will be executed? How I can test this at my computer (if I can)?


Yes, the

this.value = value;

operation is atomic. See the Java Language Specification: Threads and Locks.

Note though that threads are allowed to cache their own values of non-volatile variables, so it is not guaranteed that a successive get-operation would yield the last set value.

To get rid of these kind of data races you need to synchronize the access to the variable somehow. This can be done by

  • making the method synchronized,
  • by letting the variable be volatile or,
  • use AtomicInteger from the java.util.concurrent package. (preferred way imo)

It should also be noted that the operation would not be atomic if you changed from int to long or double. Here is a relevant section from the JLS:

17.4 Non-atomic Treatment of double and long

If a double or long variable is not declared volatile, then for the purposes of load, store, read, and write actions they are treated as if they were two variables of 32 bits each: wherever the rules require one of these actions, two such actions are performed, one for each 32-bit half.


Some useful links:

  • Wikipedia article on the Java Memory Model
  • Java Language Specification, Interaction with the Memory Model


It is atomic, because it is just a primitive 32 bit value.

Hence when you read it, there is a guarantee that you will see a value set by one of the threads, but you won't know which one it was.

If it was a long, you wouldn't have the same guarantee, although in practice most VM implementations do treat long writes as atomic operations.

This is what the JLS has to say on the issue:

VM implementors are encouraged to avoid splitting their 64-bit values where possible. Programmers are encouraged to declare shared 64-bit values as volatile or synchronize their programs correctly to avoid possible complications.

But with ints you are safe, question is, is this very weak guarantee enough for you? More often than not, the answer is a no.


First of all, assignment to all primitive types (except 64-bit ones) in Java is atomic according to the Java specification. But for instance auto-increment isn't thread-safe, no matter which type you use.

But the real problem with this code is not atomicity, but visibility. If two threads are modifying the value, they might not see the changes made by each other. Use the volatile keyword or, even better, AtomicInteger to guarantee correct synchronization and visibility.

Please note that synchronized keyword also guarantees visibility, which means if some modification happens inside synchronnized block, it is guaranteed that it will be visible by other threads.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜