Atomic Operations and multithreading

36,669

Solution 1

Doing a = 28 (with a being an int) is an atomic operation. But doing a++ is not an atomic operation because it requires a read of the value of a, an incrementation, and a write to a of the result. As a result, if you used a++ to implement a thread-safe counter, you could have two threads reading the value concurrently (26 for example), then have both increment it and writing it concurrently, resulting in 27 as a result, instead of 28.

AtomicInteger solves this issue by providing atomic operations like the ones you listed. In my example, you would use incrementAndGet() for example, which would guarantee the end value is 28 and not 27.

Solution 2

Atomic means the operation completes without any possibility for something to happen between. eg. getAndDecrement(), on AtomicInteger, guarantees that the variable is returned AND decremented at the same time.

If it was not an atomic operation, the possibility would exist for the value to get decremented (eg. from 3 to 2), then modified by another thread (eg. changing it from 2 to 5), then returned as 5.

Solution 3

You need an AtomicInteger if you need to read a variable and write a result depending on the read value. For instance, i++ reads i (e.g. 3) and writes i+1 (e.g. 4). A thread may be interrupted meanwhile, and three other threads increment i too. Now that we get back, i actually has the value 6 but our thread still writes 4, based on what it read beforehand.

AtomicInteger.getAndIncrement ensures you're not interrupted and therefore always incrementing properly. Moreover, the result is always flushed into memory, whereas a non-volatile i might not be flushed to memory. In this case other threads might not even see the changes.

Solution 4

atomicity of an operation is required when you mutate a variable. doing int a = 10; is an atomic operation but its not the one which will give you the problem. the problem giving operations usually are mutating ones like a++ or a = a + 2; and so on.

Java Specification guarantees that 'reading' and 'writing' are atomic operations not their combinations. so an operation which 'reads, adds 1 and then writes the result back' is not atomic as per specification. such operations are called compound operations and they usually need to be atomic in context of their usage in our code.

Atomic types help solve this problem. using incrementAndget() on an atomic type makes 'reads, adds 1 and then writes the result back and reads the new result' a single atomic operation in context to thread safety.

Hope this helps. By the way you should read this (http://walivi.wordpress.com/2013/08/24/concurrency-in-java-a-beginners-introduction/) article about basics of concurrency and threads. it explains such stuff beautifully.

Share:
36,669
MaheshVarma
Author by

MaheshVarma

I'm a Java Developer, Passionate about Web Programming, algorithms, Collections, Multithreading, Parellel Processing etc... I love poetry(writing and reading) based on vivid imagery.

Updated on July 20, 2020

Comments

  • MaheshVarma
    MaheshVarma almost 4 years

    Recently I was reading a tutorial, in that I came across a statement that says..

    "The Java language specification guarantees that reading or writing a variable is an atomic operation(unless the variable is of type long or double). Operations variables of type long or double are only atomic if they declared with the volatile keyword."

    AtomicInteger or AtomicLong that provides methods like getAndDecrement(), getAndIncrement() and getAndSet() which are atomic.

    I got confused a bit with the above statement.. could you please clarify when to use AtomicInteger or AtomicLong classes.