A counter with no concurrency control:
public class Counter implements Runnable {
private static int count;
public void Run () {
System.out.println (Thread.CurrentThread (). GetName ()
+ ":" + (++count));
}
public static void Main (string[] args) {
Counter Counter = new Counter ();
thread T1 = new Thread (counter);
Thread t2 = new Thread (counter);
thread t3 = new Thread (counter);
thread T4 = new thread (counter);
T1.start ();
T2.start ();
T3.start ();
T4.start ();
}
Sometimes it works, but occasionally the following results occur:
Thread-1:2
thread-0:1
thread-2:3
thread-3:3
This is obviously not the same as the expected results, first analysis of the class with the Javap-verbose command, at the bytecode level, ++count equivalent to the virtual machine in sequence to execute the following 5 bytecode instructions (regardless of runtime optimization)
Getstatic Gets the static domain of the specified class and presses its value onto the top
iconst_1 pushes the int 1 to the top of the stack
iadd adds the top two int and pushes the result onto the top of
the stack DUP Copy the top value of the stack and press the copy value onto the top
of the stack putstatic the static field of the specified class
When the Thread-3 thread executes the getstatic instruction, the Thread-2 thread has not yet executed to the iadd instruction, so the value of the initial static field count that the Thread-3 thread obtains is the same as the Thread-2 thread, 2
The essential reason is that ++count is just a line of code, but this process is not atomic operation
To guarantee this type of atomic operation, you can use the class under the Java.util.concurrent.atomic package
Package Java.util.concurrent.atomic a
small toolkit of classes that supports thread-safe programming that unlocks on a single variable.
Examples are as follows:
public class Counter implements Runnable {
private final atomicinteger count = new Atomicinteger (0);
public void Run () {
System.out.println (Thread.CurrentThread (). GetName ()
+ ":" + count.incrementandget ());
} Public
static void Main (string[] args) {
Counter Counter = new Counter ();
thread T1 = new Thread (counter);
Thread t2 = new Thread (counter);
thread t3 = new Thread (counter);
thread T4 = new thread (counter);
T1.start ();
T2.start ();
T3.start ();
T4.start ();
}
See how it's actually implemented in the source code.
private volatile int value;
Public Atomicinteger (int initialvalue) {
value = InitialValue;
}
Public final int Incrementandget () {for
(;;) {
int current = Get ();
int next = current + 1;
if (Compareandset (next)) return to
next;
}
/**
* atomically Sets the value to the given updated value
* If the current value {@code = =} The expected value.
*
* @param expect the expected value
* @param update the new value
* @return true if successful. False return indicates that
* The actual value is not equal to the expected value.
/Public
Final Boolean compareandset (int expect, int update) {return
unsafe.compareandswapint, Valueoffset, expect, update);
Public final int Get () {return
value;
}
is not the same as optimistic lock, if the results meet the expected results, return the results, or continue to retry, and did not synchronize, taking into account security and performance
There are a number of classes under the Java.util.concurrent.atomic package that use these classes to ensure that such "fetch-update" operations on these classes are atomic, avoiding the occurrence of a race condition
atomicboolean a Boolean value that can be updated atomically.
Atomicinteger an int value that can be updated in atomic mode.
Atomicintegerarray can update an int array of its elements in an atomic way.
Atomicintegerfieldupdater<t> A reflection based utility that updates the specified volatile int field for the specified class.
Atomiclong a Long value that can be updated in atomic form.
Atomiclongarray can update the long array of its elements in an atomic way.
Atomiclongfieldupdater<t> A reflection based utility that updates the specified volatile long field for a specified class.
Atomicmarkablereference<v> Atomicmarkablereference maintains object references with marked bits that can be updated in an atomic way.
Atomicreference<v> an object reference that can be updated in an atomic way.
Atomicreferencearray<e> can update an object reference array of its elements in an atomic way.
Atomicreferencefieldupdater<t,v> A reflection based utility that updates the specified volatile fields for the specified class.
Atomicstampedreference<v> Atomicstampedreference maintains an object reference with an integer "flag" that can be updated in an atomic way.