What does "atomic" mean in programming?
Asked Answered
D

7

363

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?

Domain answered 24/2, 2013 at 16:57 Comment(6)
One operation at a time.Retinue
only one operation can be performed on the variable at a time.Sair
ibm.com/developerworks/library/j-jtp11234Cesarean
i suspect philosophy questions belong in codereview.stackexchange.comIneradicable
Noting that some variables don't by default have atomic read and write, declaring them as volatile long or volatile double makes read atomic and write atomic.Fondea
Atomic comes from Greek, meaning "indivisible". en.wikipedia.org/wiki/Atomicity_(database_systems) (Databases use "atomicity" for whole transactions the same way lockless programming uses it for single operations. (Or for transactional-memory transactions))Trader
I
467

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;
Intimist answered 24/2, 2013 at 17:7 Comment(10)
Nice - didn't know that volatile long/double guaranteed atomic assignement.Fruge
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?Burgonet
@Burgonet If you are running 64 bit Java, yes.Snakebird
Does this applies to C# and .NET too? If yes, in order to foo gets an atomic behavir, the CLR must be 64-bit?Neptunium
@Neptunium It does apply and here's how to achieve it in .NET since we don't have the synchronized keyword like Java. #541694Diep
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?Antonietta
@Burgonet From Java 5.0, 64-bit operations are atomic on 32-bit JVMs as well.Lifer
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 .Revolute
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.Strikebound
In C#/.NET, several types are guaranteed always atomic, including object references. For other types, you should use locking or the Interlocked class.Strikebound
F
92

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

Fondea answered 25/6, 2014 at 13:25 Comment(5)
your second sentence is spot on. "instantaneous", however, is misleading - it's perfectly valid for two atomic operations to be observed in a different order: e.g. x=0; x=x+1; y=2 in a multithreaded program, a second thread could observe y=2, then read x is 0 - even if all assignments are atomic. atomic just means that intermediate states of the atomic operations can't be seen. In practice, both compilers and CPUs reorder instructions to improve performance, such that single-threaded code still behaves the same, but the reordering is observable from other threads.Wiseacre
@DavidGoldstein you discussed 2 atomic operations. I presume the 2 are the ones that follow x=0. In other words, x=x+1; y=2;. Anyway if these are 2 atomic operations executed in a different order, it doesn't invalidate my first sentence which tries and I think succeeds in defining an atomic operation, or perhaps I should say defining a single atomic operation.Fondea
yeah, that's fair. I guess my point is that people may read "instantaneous" and by analogy with normal expectations of linear time, make the jump to assuming linearizability - where if one operation happens before another, you see the effects in that order as well. Which is not a guarantee individual atomic operations offer when combined.Wiseacre
@DavidGoldstein My definition says "appears to be" instantaneous. Most people understand that operations are not actually instantaneous. It's just a metaphor.Fondea
@DavidGoldstein By the way, if you're concerned about 2 statements being executed in reverse order, just make the 2 statements or a series of several statements into an atomic operation. Some languages provide this in a feature called a "lock".Fondea
S
37

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.

Sobel answered 24/2, 2013 at 17:0 Comment(0)
S
21

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

Simla answered 29/9, 2014 at 5:40 Comment(0)
F
17

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

Fruge answered 24/2, 2013 at 17:9 Comment(2)
why do you think that "long" causes problem while "int" does not ? Please see here geekswithblogs.net/BlackRabbitCoder/archive/2012/08/09/…Choleric
@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.Fruge
F
4

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.

Fundus answered 26/8, 2022 at 20:26 Comment(0)
D
1

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.

Discontented answered 13/4, 2020 at 7:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.