James
James

Reputation: 3701

What does "atomic" mean in programming?

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?

Upvotes: 369

Views: 228375

Answers (8)

Abdul Alim Shakir
Abdul Alim Shakir

Reputation: 1227

According to Oracle,

In programming, an atomic action is one that effectively happens all at once. An atomic action cannot stop in the middle: it either happens completely, or it doesn't happen at all. No side effects of an atomic action are visible until the action is complete.

The shared resource in multithreading usually causes complex issues when concurrency is applied. The program or database may become inconsistent if a shared resource is impacted. Handling with the shared resource becomes essential where multiple threads access and modify shared resources. In such a case, one of the options may be an atomic variable. And there is no need of explicit synchronization using synchronized or volatile keyword.

Java package java.util.concurrent.atomic provides the following atomic classes to enable lock free mechanism and thread safety.

AtomicBoolean

AtomicInteger

AtomicIntegerArray

AtomicLong

AtomicLongArray

AtomicReference

AtomicReferenceArray

When two threads work simultaneously on a shared variable and one of those actions involves writing, both threads have to employ atomic operations. The operations of atomic classes in Java depend on CAS(Compare-And-Swap) to perform atomically, ensuring correctness and efficiency of the program in a multithreaded environment.

For Float and Double type variables, there is no atomic classes in this package. But you can use this technique described here.

Upvotes: 0

Malik Mussabeheen Noor
Malik Mussabeheen Noor

Reputation: 864

In simple words, the atomic means the operation will be either completed or not. The other threads or CPUs won't catch it in the middle of the operation.

Upvotes: 4

JB Nizet
JB Nizet

Reputation: 692121

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;

Upvotes: 473

Eugene Shamkin
Eugene Shamkin

Reputation: 183

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.

Upvotes: 1

assylias
assylias

Reputation: 328815

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

Upvotes: 17

Kurt Zhong
Kurt Zhong

Reputation: 7486

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

Upvotes: 21

H2ONaCl
H2ONaCl

Reputation: 11309

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

Upvotes: 92

Grant Thomas
Grant Thomas

Reputation: 45068

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.

Upvotes: 38

Related Questions