A concept
In the comparison and exchange computer (Conmpare And Swap i.e. CAS) is an atomic instruction for realizing multi-thread synchronization, when a plurality of threads operate on a resource for CAS, only one thread successfully, and will not block other threads but returns a failure signal.
Two basic principles
Each contains three operator CAS
1 memory address V
2 is the expected value of the old A
. 3 new B
The basic idea, if the value of V on the incoming address and the old expectations A is equal to, give an address assigned new values B, or no treatment
if(V.value.equals(A))
{
V.value = B;
return true;
}else
{
return false;
}
Common types of atomic operations
basic types AtomicInteger, AtomicLong, AtomicBoolean;
array type AtomicIntegerArray, AtomicLongArray, AtomicReferenceArray;
reference type AtomicReference, AtomicMarkableReference, AtomicStampedReference
Three common usage and ABA problem
3.1 common usage
The basic types of atomic operations (Integer)
= New new AtomicInteger of AtomicInteger of AtomicInteger (10);
// test basic types of atomic operations
public void atomicIntegerTest ()
{
// incremented by one and returns the new value
System.out.println ( "self-energizing and returns the new value =" + atomicInteger.incrementAndGet ());
// return the old value, plus. 1
System.out.println ( "return =" + atomicInteger.getAndIncrement () + "and increment");
}
result
Increment and return the new value = 11
= 11 and returns the self-energizing
purposes may be used, such as multi-threaded counting,
// Array types of atomic operations
int [] = ARR new new int [] {1,2,3,4,5,6,7,8};
Private AtomicIntegerArray atomicArray = new new AtomicIntegerArray (ARR);
@Test
public void Test ()
{
// Get index value of 0, and 0 in the index modification value. 3
System.out.println (atomicArray.getAndSet (0,3));
System.out.println ( "source array index 0 =" + arr [0]) ;
System.out.println ( "atom type of the array index 0 =" + atomicArray.get (0));
}
Results
1
Original array index value = 0, 1
Atom type array index value of 0. 3 =;
3.2 issues the ABA
A value of the original address V
1. 1 time thread 1 performs a read operation, acquires the original value A, then thread switch away
2. Thread 2 updates the time value of 2 on B V
3. 3 time thread 2 updates the value of A in the V
4. the thread 1 to resume operation timing 4, the comparison value (compareValue) with the original value (oldValue) were compared, two values are equal (both A).
Then (newValue) B written into the memory with new values, the operation completion CAS
We can find, in fact, the value of V, before the thread Amendment 1 has been changed 2 times (read B, and back to A)
but does not know the original value of the thread 1 is modified, so continue the process.
ABA deal with the problem
Generally the operation is provided every CAS version of the stamp, currently offers two classes atoms at java.util.concurrent.atomic package
AtomicMarkableReference AtomicStampedReference
Version version stamp stamp is a boolean type is the type of number
Only care about whether the data have been altered several times passive interest data
See specific examples
AtomicStampedRefernceTest class {public
// version stamp with atomic
private static AtomicStampedReference <String> atomicStampedReference = new AtomicStampedReference <> ( " author", 1);
// old version stamp
Final oldstamp int = atomicStampedReference.getStamp ();
// The old value
Final oldValue String = atomicStampedReference.getReference ();
@Test
public void mainTest () {
the thread right = new new the thread (new new rightThread ());
// correct version number of threads
// wrong version number of threads
thread error = new thread ( errorThread new new ());
the try {
right.start ();
right.join ();
error.start ();
error.join ();
the catch} (InterruptedException EX)
{
ex.printStackTrace ();
}
}
// properly using the CAS version number of threads
public class rightThread the implements the Runnable {
@Override
public void RUN () {
String value = atomicStampedReference.getReference ();
Stamp atomicStampedReference.getStamp = int ();
. Thread.currentThread () setName ( "the right to use the version number of threads");
System.out.println (Thread.currentThread () getName () +. ": value =" + value + "stamp version =" + stamp + "CAS result =" +
atomicStampedReference.compareAndSet (value, value + "- handsome", stamp, stamp + 1) );
}
}
// use the wrong version number of the CAS thread
public class errorThread implements Runnable {
@Override
public void run() {
String value = atomicStampedReference.getReference();
int stamp = atomicStampedReference.getStamp();
Thread.currentThread().setName("错误使用了版本号线程");
System.out.println(Thread.currentThread().getName() + ":值=" + value + ",版本戳=" + stamp + " CAS结果=" +
atomicStampedReference.compareAndSet(value, value + "-老者", oldstamp, oldstamp + 1));
}
}
}
Output
Proper use of the version number of threads: value = author, version stamp = 1 CAS result = true
misuse of the version number of threads: value = Author - handsome, version stamp = 2 CAS result = false
to sum up:
CAS and synchronized What is the difference?
java is built synchronized lock for locking the object is a piece of resources to ensure that this is only one thread to access the resource (i.e., resource ensure atomicity), pessimistic locking.
CAS operation is an atomic-level computer instructions
What is the use of synchronized inconvenient place or disadvantages?
1 synchronized mechanism is based on blocking if the lock will block a thread can not get in there, when the high-priority thread is blocked, we can not interrupt
2 threads to get the lock has not released how do
3 lock a lot of competition, there will be a deadlock or livelock, and will consume CPU, and other security issues
The drawbacks of using CAS
in order to ensure the success of the CAS operation, calling the cycle you die, until it is successful, resulting in CPU overhead problem
Under what circumstances CAS?
When that locks inconvenient, or too heavy, you can consider using CAS