Conteúdo do Curso
Multithreading in Java
Multithreading in Java
Atomic Variables
We’ve already covered what atomicity is and the problems it can cause in the first section of this course. Back then, we addressed the issue using synchronized blocks or methods. Now, we’ll explore how to achieve the same result more easily by using an atomic class.
What are Atomic Variables?
Atomic variables ensure that operations (read, write, increment) on variables are performed atomically, meaning they are executed contiguously and safely in a multithreaded environment. This guarantees that the operation will be completed entirely, without the possibility of interference from other threads during its execution.
Why do We Need Atomic Variables?
Without the use of atomic variables or other synchronization mechanisms, operations like increment (++)
can be unsafe. For instance, when multiple threads access the same variable simultaneously, updates might be lost, resulting in incorrect results. Atomic variables solve this problem by ensuring that operations on them are executed sequentially.
We previously discussed this issue when the increment operation was broken down into three steps (read, increment, write), but with atomic variables, it’s all done in one operation!
Types of Atomic Variables in Java
Note
In general, there are many atomic implementations, and we won’t cover them all here, as it would take too long.
Java provides several atomic variable classes in the java.util.concurrent.atomic
package, each designed to handle a specific data type:
AtomicInteger
: for atomic operations on int;AtomicLong
: for atomic operations on long;AtomicBoolean
: for atomic operations on boolean;AtomicReference<V>
: for atomic operations on objects (generic type).
Methods
The get()
method returns the current value of a variable. The set(V newValue)
method sets a new value for the variable. On the other hand, lazySet(V newValue)
is similar to set()
, but it can defer updating the value, offering an ordered update in certain situations.
Main
The compareAndSet(V expect, V update)
method updates the value if the current value matches the expected value. It returns true
if the update was successful, and false
if the current value did not match the expected value. In contrast, the getAndSet(V newValue)
method sets a new value and returns the previous value.
Main
The getAndIncrement()
and getAndDecrement()
methods increment or decrement the current value by one and return the previous value. These methods apply to numeric atomic variables such as AtomicInteger
and AtomicLong
. In contrast, the incrementAndGet()
and decrementAndGet()
methods also increment or decrement the current value by one but return the new value.
Main
The getAndAdd(int delta)
method adds the specified value (delta) to the current value and returns the previous value. This method is used with numeric atomic variables. On the other hand, the addAndGet(int delta)
method also adds the specified value (delta) to the current value but returns the new value.
Main
Examples of Using Atomic Variables
Example with AtomicInteger
(AtomicLong
, AtomicBoolean
are the same, so there will be no separate examples for them).
Task: To implement a counter that is safely incremented by several threads.
Main
As you can see we didn't use any synchronization here, as the atomic variable itself provides this function
This example uses AtomicInteger
to safely increment the counter. The getAndIncrement()
method first returns the current value of the variable, then increments it by one. This happens atomically, ensuring that the variable is updated correctly.
Example with AtomicReference
Task: Provide atomic updating of a reference to an object.
Main
AtomicReference
is used here to atomically update the value of a string reference. The getAndSet()
method atomically sets the new value and returns the previous value.
Note
Unlike regular variables, which require additional *synchronization, atomic variables utilize low-level primitives to minimize overhead and enhance performance. This makes them particularly well-suited for high-concurrency systems.
Tudo estava claro?