What does "atomic" mean in programming?

JavaAtomic

Java Problem Overview


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?

Java Solutions


Solution 1 - Java

Here's an example: Suppose foo is a variable of type long, then the following operation is not an atomic operation (in Java):

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;

Solution 2 - Java

"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.

Solution 3 - Java

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.

Solution 4 - Java

Just found a post [Atomic vs. Non-Atomic Operations][1] 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."

[1]: http://preshing.com/20130618/atomic-vs-non-atomic-operations/ "Atomic vs. Non-Atomic Operations"

Solution 5 - Java

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).

Solution 6 - Java

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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJamesView Question on Stackoverflow
Solution 1 - JavaJB NizetView Answer on Stackoverflow
Solution 2 - JavaH2ONaClView Answer on Stackoverflow
Solution 3 - JavaGrant ThomasView Answer on Stackoverflow
Solution 4 - JavaKurt ZhongView Answer on Stackoverflow
Solution 5 - JavaassyliasView Answer on Stackoverflow
Solution 6 - JavaEugene ShamkinView Answer on Stackoverflow