Java Reference
In-Depth Information
Listing 6-28.
A Counter Class That Uses Synchronization
// SynchronizedCounter.java
package com.jdojo.threads;
public class SynchronizedCounter {
private long value;
public synchronized long next() {
return ++value;
}
}
You would rewrite the
SynchronizedCounter
class using the
AtomicLong
class as shown in Listing 6-29.
Listing 6-29.
A Counter Class Using Atomic Variable
// AtomicCounter.java
package com.jdojo.threads;
import java.util.concurrent.atomic.AtomicLong;
public class AtomicCounter {
private AtomicLong value = new AtomicLong(0L);
public long next() {
return value.incrementAndGet();
}
}
Note that the
AtomicCounter
class does not use any explicit synchronization. It takes advantage of CAS
hardware instruction. The call to the
incrementAndGet()
method inside the
next()
method of the
AtomicCounter
class is performed atomically for you. You can also use an object of the
AtomicLong
class as a thread-safe counter
object like so:
AtomicLong aCounter = new AtomicLong(0L);
Then you can use the
aCounter.incrementAndGet()
method to generate a new counter. The
incrementAndGet()
method of the
AtomicLong
class increments its current value and returns the new value. You also have its counterpart
method called
getAndIncrement()
, which increments its value and returns its previous value.
The
AtomicXxx
variable classes have a
compareAndSet()
method. It is a variant of compare and swap (CAS).
The only difference is that the
compareAndSet()
method returns a
boolean
. It returns
true
if it succeeds; otherwise it
returns
false
. The following is the pseudo code representation of the
compareAndSet()
method:
compareAndSet(M, O, N) {
// Call CAS (see CAS pseudo code) if CAS succeeded, return true;
// otherwise, return false.
return (CAS(M, O, N) == O)
}