What is it
- Full name compare and swap, a CPU Atom directive, implemented at the hardware level, embodies the idea of optimistic locking.
- The JVM encapsulates assembly calls in C language. There are many classes in the base library of Java, which is the function of multithreading synchronization update based on JNI call C interface.
Principle
CMS has three operands: the value of the current main memory variable v, thread local variable expected value A, thread local to update value B. When the value of the variable needs to be updated, it gets to the memory variable value V and then the expected value A is compared, if the same is updated to B, if different, the latest variable value is updated to the expected value and then retry the above steps until successful.
Example
The Atomicinteger class based on CAS is explained.
We first write a multi-threaded, the same data class to add and subtract operations 10,000 times, the correct result should be 0.
There is no multithreaded synchronization mechanism with the following code:
PackagePriv.nanjing.testCasClass;/** @Author: Darrenqiao **///data classes for multithreaded contentionclassCounter {intCount = 0; Public intGetCount () {returncount; } Public voidSetCount (intcount) { This. Count =count; } Public voidAdd () {count+ = 1; } Public voidDec () {Count-= 1; }}//threads that compete for data to be added to the OperationclassAdddatathreadextendsThread {Counter Counter; PublicAdddatathread (Counter Counter) { This. Counter =counter; } @Override Public voidrun () { for(inti = 0; i < Casclass.loop; ++i) {counter.add (); } }}//the thread that contentions the data to do the subtraction operationclassDecdatathreadextendsThread {Counter Counter; PublicDecdatathread (Counter Counter) { This. Counter =counter; } @Override Public voidrun () { for(intj = 0; J < Casclass.loop; J + +) {Counter.dec (); } }} Public classCasclass {Final Static intLOOP = 10000; Public Static voidMain (string[] args)throwsinterruptedexception {Counter Counter=NewCounter (); Thread Addthread=Newadddatathread (counter); Thread Decthread=Newdecdatathread (counter); Addthread.start (); Decthread.start (); Addthread.join (); Decthread.join (); System.out.println (Counter.getcount ()); }}
Here are three execution results, each of which is different.
Why does this result occur?
Because the Count + = 1/count-= 1 is javap to decompile the Count.class file, you can see that the corresponding byte code is three instructions
// count + = 1 5: iconst_1 6: Iadd 7:putfield #12 // Field count:i // count 1= 1 5: iconst_1 6: isub 7:putfield #12 // Field count:i
So the multi-threaded switch is, may cause the data update the different step, how solves ?
is to be manipulated data lock, can be pessimistic lock, can be optimistic lock, here is based on optimistic lock implementation of the Atomicinteger class
PackagePriv.nanjing.testCasClass;ImportJava.util.concurrent.atomic.AtomicInteger;/** @Author: Darrenqiao **///data classes for multithreaded contentionclassCounter {//int count = 0; //MakeReplace basic data types with AtomicintegerAtomicinteger count =NewAtomicinteger (0); Public intGetCount () {//return count; returnCount.get (); } Public voidAdd () {//count + = 1;Count.addandget (1); } Public voidDec () {//count-= 1;Count.decrementandget (); }}//threads that compete for data to be added to the OperationclassAdddatathreadextendsThread {Counter Counter; PublicAdddatathread (Counter Counter) { This. Counter =counter; } @Override Public voidrun () { for(inti = 0; i < Casclass.loop; ++i) {counter.add (); } }}//the thread that contentions the data to do the subtraction operationclassDecdatathreadextendsThread {Counter Counter; PublicDecdatathread (Counter Counter) { This. Counter =counter; } @Override Public voidrun () { for(intj = 0; J < Casclass.loop; J + +) {Counter.dec (); } }} Public classCasclass {Final Static intLOOP = 10000; Public Static voidMain (string[] args)throwsinterruptedexception {Counter Counter=NewCounter (); Thread Addthread=Newadddatathread (counter); Thread Decthread=Newdecdatathread (counter); Addthread.start (); Decthread.start (); Addthread.join (); Decthread.join (); System.out.println (Counter.getcount ()); }}
Executed several times, you will find that the result is only one: 0. This guarantees the atomicity of data updates.
So what are the shortcomings of CAs to note ?
- ABA Problem: My memory object changes from A to B when it becomes a,cas as if there is no change and then updates the value.
- The cycle time overhead is large: it always loops when the expected value is not correct.
- Only atomic operations of a shared variable can be guaranteed.
Java optimistic lock implementation-cas