Java. util. Concurrent. Atomic. Atomic * atomic class and volatile keyword are two common methods in Java to process data shared read/write under multiple threads. The two seem to be the same, but they are quite different in practical applications.
The volatile keyword is a write lock implemented by local code. It only ensures that a thread is writing data. To speed up data access, the JVM allows each thread to perform private copy of the data shared in the process in its own independent data blocks. Volatile ensures that data in shared data blocks is read every time, rather than private copies. However, this mechanism is not secure in some situations. When two threads t1 and t2 simultaneously perform I ++ on volatitle int I;, the problem may occur. I ++ is equivalent to I = I + 1.
T1 load I
T2 load I
T1 store I + 1
T2 store I + 1
Here we should execute I = I + 1 twice to get the I = I + 2, but the result is indeed I = I + 1.
Therefore, there is a value for the existence of atomic classes. The atomic class is designed to solve this problem.
Taking atomicinteger as an example, public class atomicinteger extends number implements java. Io. serializable.
Its parent class number does not have a field and directly inherits from the object. The method also has only abstract int intvalue (), long longvalue (), float floatvalue (), double doublevalue (), and byte bytevalue (), short implements value () through intvalue (). Simply put, there are no fields except serialization.
Atomicinteger has four fields. In addition to serialization, there are three fields left.
// Setup to use unsafe. compareandswapint for updates
Private Static final unsafe = unsafe. getunsafe ();
Private Static final long valueoffset;
Static {
Try {
Valueoffset = unsafe. objectfieldoffset
(Atomicinteger. Class. getdeclaredfield ("value "));
} Catch (exception ex) {Throw new error (Ex );}
}
Private volatile int value;
Valueoffset is only written in this static block. From the function name, it is estimated that the offset from the field named value in this class to the header pointer of this object is obtained ). Unsafe is used here.
What does unsafe do? Sun. Misc. Unsafe, not open source. This name reminds me of the keyword unsafe in C. C # In order to facilitate the conversion of C ++ programmers to C # and facilitate the use of COM components, the unsafe keyword of Insecure code is provided. Java unsafe, which can offset a field from its object header, is obviously insecure for Java, and it is possible for users to directly operate the memory.
In addition to objectfieldoffset (field), this class also uses the putorderedint (object, long, INT) and compareandswapint (object, long, Int, INT) of unsafe ). From the method name and parameters, the function is to offset the long position to the object, write an ordered integer int, and compare whether the two values are the same, and fill in the new value.
Here is an IBM document on compareandswapint. I can see it after writing it... Http://www.ibm.com/developerworks/cn/java/j-jtp11234/
By the way, the source code of the two methods called to compareandswapint: compareandset and weakcompareandset are the same in section 1.6... Is it fun to write redundant code? I can't understand it in API...
The next field is the private volatile int value. Volatitle is also used, and it can be concluded that the efficiency of the atomic class is lower than that of the volatitle class.
Let's take a look at the atomicinteger method.
The values inherited from the number parent class can be considered as the value class of the getter function. The get () method is called in a clear way and the type is converted.
Public final int get (){
Return value;
}
The value is directly thrown back. It can be seen that there is no difference between the atomic class and the volatitle class in processing read operations.
It looks like there are five setter functions:
Public final void set (INT newvalue ){
Value = newvalue;
}
Public final void lazyset (INT newvalue ){
Unsafe. putorderedint (this, valueoffset, newvalue );
}
Public final int getandset (INT newvalue ){
For (;;){
Int current = get ();
If (compareandset (current, newvalue ))
Return Current;
}
}
Public final Boolean compareandset (INT exact CT, int update ){
Return unsafe. compareandswapint (this, valueoffset, exact CT, update );
}
Public final Boolean weakcompareandset (INT exact CT, int update ){
Return unsafe. compareandswapint (this, valueoffset, exact CT, update );
}
There is no difference between weakcompareandset and compareandset, so ignore it. Actually, atomicinteger only uses compareandset...
Set (INT) is no different from using volatitle directly. Therefore, using set for writing is almost the same as not using the atomic class at all, and more calls to the sequence function.
Lazyset (INT) calls unsafe. putorderedint. We can only guess that a number is written directly to the memory. In this case, actually... I don't think there is any difference. I just want to tell you that you can use unsafe to write Java as C ++...
Getandset (INT) calls compareandset (INT, INT). Basically, it keeps refreshing and you can see if you have changed it to "no". It has been changed to "saved". You have not changed it to "continue to change. There are two threads here to keep changing...
The last compareandset (INT, INT) is where the atomic class function is implemented. It is like whether it is the same as expected. If it is the same, it will be replaced with a new value. If it is different, false will be returned. How to use it? Check that other functions are available.
Comparison between getandincrement () and incrementandget ()
Public final int getandincrement (){
For (;;){
Int current = get ();
Int next = Current + 1;
If (compareandset (current, next ))
Return Current;
}
}
Public final int incrementandget (){
For (;;){
Int current = get ();
Int next = Current + 1;
If (compareandset (current, next ))
Return next;
}
}
The difference is that the former returns the modified value, and the latter returns the modified value. The usage of compareandset is as follows.
For more information about other mechanisms, see http://www.ibm.com/?works/cn/java/j-jtp#34/. the performance comparison of several Synchronous machines is important.