Atomic Methods
Java provides atomic methods. Here is a list of some of the classes in this package and their short description:
Method Type |
Description |
int addAndGet(int delta) |
Atomically adds the given value to the current value. |
boolean compareAndSet(int expect, int update) |
Atomically sets the value to the given updated value if the current value == the expected value. |
int decrementAndGet() |
Atomically decrements by one the current value. |
double doubleValue() |
Returns the value of the specified number as a double. |
float floatValue() |
Returns the value of the specified number as a float. |
int get() |
Gets the current value. |
int getAndAdd(int delta) |
Atomically adds the given value to the current value. |
int getAndDecrement() |
Atomically decrements by one the current value. |
int getAndIncrement() |
Atomically increments by one the current value. |
int getAndSet(int newValue) |
Atomically sets to the given value and returns the old value. |
int incrementAndGet() |
Atomically increments by one the current value. |
int intValue() |
Returns the value of the specified number as an int. |
void lazySet(int newValue) |
Eventually sets to the given value. |
long longValue() |
Returns the value of the specified number as a long. |
void set(int newValue) |
Sets to the given value. |
String toString() |
Returns the String representation of the current value. |
boolean weakCompareAndSet(int expect, int update) |
Atomically sets the value to the given updated value if the current value == the expected value. |
Apply Atomic Variables and Locks
(OCP Objective 11.2) for 1Z0-804
11.2 Use Lock, ReadWriteLock, and ReentrantLock classes in the java.util.concurrent. locks package to support lock-free thread-safe programming on single variables.
The java.util.concurrent.atomic and java.util.concurrent.locks packages solve two different problems. They are grouped into a single exam objective simply because they are the only two packages below java.util.concurrent
and both have a small number of classes and interfaces to learn. The java.util .concurrent.atomic
package enables multithreaded applications to safely access individual variables without locking, while the java.util.concurrent.locks package provides a locking framework that can be used to create locking behaviors that are the same or superior to those of Java's synchronized keyword.
Atomic Variables
Imagine a multiplayer video game that contains monsters that must be destroyed.
The players of the game (threads) are vanquishing monsters, while at the same time a monster-spawning thread is repopulating the world to ensure players always have a new challenge to face. To keep the level of difficulty consistent, you would need to keep track of the monster count and ensure that the monster population stays the same (a hero's work is never done). Both the player threads and the monsterspawning thread must access and modify the shared monster count variable. If the monster count somehow became incorrect, your players may find themselves with more adversaries than they could handle. The following example shows how even the seemingly simplest of code can lead to undefined results. Here you have a class that increments and reports the current value of an integer variable:
public class Counter {
private int count;
public void increment() {
count++; // it's a trap!
// a single "line" is not atomic
}
public int getValue() {
return count;
}
}
A Thread that will increment the counter 10,000 times:
public class IncrementerThread extends Thread {
private Counter counter;
// all instances are passed the same counter
public IncrementerThread(Counter counter) {
this.counter = counter;
}
public void run() {
// "i" is local and thread-safe
for(int i = 0; i < 10000; i++) {
counter.increment();
}
}
}
The code from within this application's main method:
Counter counter = new Counter(); // the shared object
IncrementerThread it1 = new IncrementerThread(counter);
IncrementerThread it2 = new IncrementerThread(counter);
it1.start(); // thread 1 increments the count by 10000
it2.start(); // thread 2 increments the count by 10000
it1.join(); // wait for thread 1 to finish
it2.join(); // wait for thread 2 to finish
System.out.println(counter.getValue()); // rarely 20000
// lowest 11972