309

In the Effective Java book, it states:

The language specification guarantees that reading or writing a variable is atomic unless the variable is of type long or double [JLS, 17.4.7].

What does "atomic" mean in the context of Java programming, or programming in general?

csano
  • 12,342
  • 2
  • 25
  • 44
James
  • 3,093
  • 3
  • 11
  • 4

6 Answers6

398

Here's an example, because an example is often clearer than a long explanation. Suppose foo is a variable of type long. The following operation is not an atomic operation:

foo = 65465498L;

Indeed, the variable is written using two separate operations: one that writes the first 32 bits, and a second one which writes the last 32 bits. That means that another thread might read the value of foo, and see the intermediate state.

Making the operation atomic consists in using synchronization mechanisms in order to make sure that the operation is seen, from any other thread, as a single, atomic (i.e. not splittable in parts), operation. That means that any other thread, once the operation is made atomic, will either see the value of foo before the assignment, or after the assignment. But never the intermediate value.

A simple way of doing this is to make the variable volatile:

private volatile long foo;

Or to synchronize every access to the variable:

public synchronized void setFoo(long value) {
    this.foo = value;
}

public synchronized long getFoo() {
    return this.foo;
}
// no other use of foo outside of these two methods, unless also synchronized

Or to replace it with an AtomicLong:

private AtomicLong foo;
Basil Bourque
  • 218,480
  • 72
  • 657
  • 915
JB Nizet
  • 633,450
  • 80
  • 1,108
  • 1,174
  • Nice - didn't know that volatile long/double guaranteed atomic assignement. – assylias Feb 24 '13 at 17:26
  • 83
    So this is assuming that it is running in a 32-bit system. What if it was 64 bit system? Will foo = 65465498L; be atomic then? – Harke Dec 24 '13 at 20:36
  • 52
    @Harke If you are running 64 bit Java, yes. – Jeroen Apr 21 '14 at 12:47
  • 4
    Does this applies to C# and .NET too? If yes, in order to foo gets an atomic behavir, the CLR must be 64-bit? – Fabiano Sep 21 '15 at 15:59
  • 5
    @Fabiano It does apply and here's how to achieve it in .NET since we don't have the synchronized keyword like Java. http://stackoverflow.com/questions/541194/c-sharp-version-of-javas-synchronized-keyword – The Muffin Man Nov 18 '15 at 18:22
  • 2
    Then let's assume thread A assigns long value then in half way thread B tries to read it. If operation A is atomic, then thread B will wait till it finishes? This means atomic operations will supply implicit thread-safety? – Teoman shipahi Sep 30 '16 at 13:58
  • @Harke From Java 5.0, 64-bit operations are atomic on 32-bit JVMs as well. – Peter Lawrey Oct 27 '17 at 08:40
  • How `volatile ` or `AtomicLong` guarantees that another thread doesn't see the part value while there are two separate operations ? And at the same time there may has thread context switch between two operations . – shaoyihe Nov 16 '18 at 03:40
  • Please note that the `volatile` keyword used in this way only applies to Java. In C or C++, the `volatile` keyword does not guarantee atomicity, but instead tries to guarantee that a change made in one thread is always visible in another—partial reads and writes are still possible. – fluggo Apr 28 '21 at 17:42
  • In C#/.NET, [several types are guaranteed always atomic](https://stackoverflow.com/questions/2076461/how-does-c-sharp-guarantee-the-atomicity-of-read-write-operations), including object references. For other types, you should use locking or the [Interlocked class](https://docs.microsoft.com/en-us/dotnet/api/system.threading.interlocked?view=net-5.0). – fluggo Apr 28 '21 at 17:46
74

"Atomic operation" means an operation that appears to be instantaneous from the perspective of all other threads. You don't need to worry about a partly complete operation when the guarantee applies.

H2ONaCl
  • 8,715
  • 11
  • 56
  • 100
29

It's something that "appears to the rest of the system to occur instantaneously", and falls under categorisation of Linearizability in computing processes. To quote that linked article further:

Atomicity is a guarantee of isolation from concurrent processes. Additionally, atomic operations commonly have a succeed-or-fail definition — they either successfully change the state of the system, or have no apparent effect.

So, for instance, in the context of a database system, one can have 'atomic commits', meaning that you can push a changeset of updates to a relational database and those changes will either all be submitted, or none of them at all in the event of failure, in this way data does not become corrupt, and consequential of locks and/or queues, the next operation will be a different write or a read, but only after the fact. In the context of variables and threading this is much the same, applied to memory.

Your quote highlights that this need not be expected behaviour in all instances.

Grant Thomas
  • 42,191
  • 8
  • 81
  • 120
17

Just found a post Atomic vs. Non-Atomic Operations to be very helpful to me.

"An operation acting on shared memory is atomic if it completes in a single step relative to other threads.

When an atomic store is performed on a shared memory, no other thread can observe the modification half-complete.

When an atomic load is performed on a shared variable, it reads the entire value as it appeared at a single moment in time."

Kurt Zhong
  • 6,748
  • 1
  • 17
  • 15
15

If you have several threads executing the methods m1 and m2 in the code below:

class SomeClass {
    private int i = 0;

    public void m1() { i = 5; }
    public int m2() { return i; }
}

you have the guarantee that any thread calling m2 will either read 0 or 5.

On the other hand, with this code (where i is a long):

class SomeClass {
    private long i = 0;

    public void m1() { i = 1234567890L; }
    public long m2() { return i; }
}

a thread calling m2 could read 0, 1234567890L, or some other random value because the statement i = 1234567890L is not guaranteed to be atomic for a long (a JVM could write the first 32 bits and the last 32 bits in two operations and a thread might observe i in between).

assylias
  • 297,541
  • 71
  • 621
  • 741
  • why do you think that "long" causes problem while "int" does not ? Please see here http://geekswithblogs.net/BlackRabbitCoder/archive/2012/08/09/c.net-little-wonders-interlocked-increment-decrement-and-add.aspx – onmyway133 Sep 26 '13 at 07:28
  • 1
    @entropy long and double assignments are not guaranteed to be atomic in Java. So you could read a long where only half of the bits have been updated following an assignment. – assylias Sep 26 '13 at 07:38
0

In Java reading and writing fields of all types except long and double occurs atomically, and if the field is declared with the volatile modifier, even long and double are atomically read and written. That is, we get 100% either what was there, or what happened there, nor can there be any intermediate result in the variables.

Eugene Shamkin
  • 135
  • 3
  • 11