This article says that the class in the java.util.concurrent.atomic bag, a total of 12. There are very many articles on the Web parsing these classes. Here are some key points to talk about.
These 12 classes can be divided into three groups:
1. Common types of atomic variables
2. Atomic variables of the array type
3. Domain Updater
6 of ordinary types of atomic variables,
1. Atomicboolean, Atomicinteger, Atomiclong, atomicreference respectively, corresponding boolean, int, long, object complete the main atomic operation
2. Atomicmarkablereference, Atomicstampedreference is a feature-enhanced version of Atomicreference that can bind a reference to a Boolean, The latter is able to bind the reference and the version number of an int to complete the timestamp function.
Atomicboolean, Atomicinteger, Atomiclong, atomicreference the structures of these classes are similar, with several features
1. The bottom layer is the use of the Sun.misc.Unsafe class to complete the actual CAS operation
2. Use Sun.misc.Unsafe to directly manipulate memory objects to complete the object property access capability similar to the reflection mechanism
3. The value of the volatile type holds the state
4. The get (), set () method of the Atom
5. Main Compareandset method Complete CAs operation
6. Weakcompareandset, weakened the version number of the CAS operation, which is the API design is reserved to differentiate the interface, but there is no implementation, now and Compareandset is the same function
7. The Getandset method is to use the CAS operation to read and set the function without locking
8. Lazyset method Optimization settings, Lazyset use see this chat high concurrency (18) Understanding Atomicxxx.lazyset Method
Atomic variables are a major tool in concurrent programming and can be used to implement non-clogging data structures and build related infrastructure artifacts.
There are several main ways to use it:
1. Safe counter
2. The Compareandset method can realize the function of "filter screen". Find the thread for the first successful operation, and do some work to see the spin lock related implementations
3. The Compareandset method enables the ability to "infer whether the operation is successful." There will be ABA problem, can use atomicstampedreference to avoid ABA problem
4. The Getandset method enables the complete "set and return to previous value" function
5. Atomicboolean as a binary state can be used as a "switch" to achieve a thread to find an open switch. For example if (B.compareandset (False, True)) {//dosomething}
Take a look at some typical operations
public class Atomicboolean implements java.io.Serializable {private static final long Serialversionuid = 4654671469794 556979L; Setup to use Unsafe.compareandswapint for updates private static final unsafe unsafe = unsafe.getunsafe (); Private static final long valueoffset; Set the value of the property by using unsafe to manipulate the memory directly {try {Valueoffset = Unsafe.objectfieldoffset (Atomicboolean. Class.getdeclaredfield ("value")); } catch (Exception ex) {throw new Error (ex);} }//Use volatile variable to save state private volatile int value; Use unsafe Compareandswapxxx method to complete the underlying CAS operation public final Boolean Compareandset (Boolean expect, Boolean update) {I NT E = expect? 1:0; int u = update? 1:0; RET Urn Unsafe.compareandswapint (this, Valueoffset, E, u); }//Lock-free implementation of the "set up and return to previous value" function, the feature of no lock is polling plus CAS Operation pub Lic Final Boolean Getandset (Boolean newvalue) { for (;;) { Boolean current = Get (); if (Compareandset (current, newvalue)) return current; } }//optimize Volatie variable write, no need to ensure visibility of the scene using Lazyset to optimize, reduce memory barrier public final void Lazyset (Boole An newvalue) { int v = newvalue? 1:0; & nbsp Unsafe.putorderedint (this, Valueoffset, v); }
Atomicmarkablereference and Atomicstampedreference are both enhancements to atomicreference, with immutable objects used internally to hold a two-dollar state <reference, Xxx> When the atom is set. The new object is created. and point the Volaitle reference to the most recent immutable object. See a lot of other things. High concurrency (12) Analyzing java.util.concurrent.atomic.AtomicStampedReference source code to see how to solve the ABA problem in CAs
Atomicmarkablereference can be used to mark objects. Often used to construct data structures that represent nodes. Ability to use Boolean to indicate whether a node has been deleted
public class Atomicmarkablereference<v> {private static class Pair<t> {final T reference; Final Boolean mark; Private Pair (T reference, Boolean mark) {this.reference = reference; This.mark = Mark; } static <T> pair<t> of (T reference, Boolean mark) {return new pair<t> (reference, Mar k); }} private volatile pair<v> Pair; Public Atomicmarkablereference (V initialref, Boolean initialmark) {pair = Pair.of (Initialref, Initialmark); } public boolean compareandset (v expectedreference, v Newreference, Boolean expectedmark, Boolean NewMark ) { pair<v> current = pair; return Expectedreference = = Current.reference && Expectedmark = = Current.mark && (newreference = = Current.reference && NewMark = = Current.mark) | | Caspair (Current, Pair.of (Newreference,NewMark)); }
There are 3 atomic variables for the array type: Atomicintegerarray, Atomiclongarray, Atomicreferencearray, which are the array version numbers of the ordinary atomic variables. The atomic operation of the elements in the array can be completed.
The main method is similar to the ordinary atomic type, here is not repeated, mentioning the use of unsafe reading array elements of the method
1. Use Unsafe.arraybaseoffset to get the offset of the first element of the array, due to the existence of the object header. So offset doesn't start at 0.
2. Use Unsafe.arrayindexscale to get the length of the elements in the array
3. Use shift operation instead of multiplication to improve efficiency. So the shift, for example, 8-byte-length elements, is calculated first. Need to move left 3 bits, equivalent to 2 of 3 power, 4 byte length of the element left 2 bits, equivalent to 2 power of 2
4. calculate the actual position of the elements in the array = Index << SHIFT + base. To be blunt, the index * element length + base
public class Atomicintegerarray implements java.io.Serializable {private static final unsafe unsafe = Unsafe.getunsafe (); Gets the offset of the first element of the array offset, due to the existence of the object header, so offset is not starting from 0 private static final int base = Unsafe.arraybaseoffset (int[].cl ); The base of the shift operation, replacing the multiplication private static final int shift with the shift operation; Private final int[] array; static {//Gets the length of the array element for the int[] array. Scale = 4 int scale = Unsafe.arrayindexscale (Int[].class); If the length is not a power of 2, the error if (Scale & (scale-1) = = 0) throw new error ("Data type scale not a power of "); 31-integer.numberofleadingzeros (scale) is equivalent to floor (log2 (x)), here is 2. Suppose a long, or 3//is actually replaced by a shift operation, for example, 4 byte length, to the left 2 bits, 8 byte length, it is necessary to shift left 3 bits. Move left 1 bit = multiply 2 shift = 31-integer.numberofleadingzeros (scale); } Private long Checkedbyteoffset (int i) {if (I < 0 | | I >= array.length) throw new INDEXOUTOFB Oundsexception ("index" + i); return Byteoffset (i); } Replacing multiplication with a shift operation actually asks for the offset of the first element of the array, conveniently locating the memory address of the array element private static long byteoffset (int i) {return ((long) I <& Lt SHIFT) + base; }
Last look at the domain updater, there are three: Atomicintegerfieldupdate, Atomiclongfieldupdate, atomicreferencefieldupdate
A domain updater is an optimization method that provides a reflection-based view of an existing volatile domain. This enables CAS operations on existing volatile domains. We know that volatile fields only guarantee visibility, but there is no guarantee of atomicity,
Suppose you want to perform CAS operations on volatile fields. You need to use the domain updater. It has the advantage of being able to have a volatile field with an atomic variable, without actually creating so many atomic variables, which are lightweight compared to atomic variables.
The domain updater does not provide a constructor for the external, it needs to be created using a factory method. Provides a newupdater (XXX) method to return a newly created Domain Updater object.
1. Tclass refers to the class type in which the field is located
2. Vclass refers to the class type of the field, it is important to note that the field must be volatile, or it will throw an exception
3. filedname Field Name
4. Caller's type, can be obtained with reflection.getcallerclass ()
public static <u, w> atomicreferencefieldupdater<u,w> newupdater (class<u> tclass, Class<W> Vclass, String fieldName) {return new atomicreferencefieldupdaterimpl<u,w> (Tclass, Vclass, FieldName, Reflection.getcallerclass ()); } Atomicreferencefieldupdaterimpl (class<t> tclass, class<v> vclass, String FieldName, class<?> caller) { Field field = null; Class Fieldclass = null; & nbsp; int modifiers = 0; Try { field = Tclass.getdeclaredfield (fieldName); modifiers = field.getmodifiers (); sun.reflect.misc.ReflectUtil.ensureMemberAccess ( & nbsp; Caller, tclass, NULL, modifiers); sun.reflect.misc.ReflectUtil.checkPackageAccess (Tclass); Fieldclass = Field.gettype (); catch (Exception ex) { throw new RuntimeException (ex); } if (vclass! = Fieldclass) throw new ClassCastException (); if (! Modifier.isvolatile (modifieRS) throw new IllegalArgumentException ("must be volatile type"); This.cclass = (modifier.isprotected (modifiers) && Caller! = Tclass)? caller:null; This.tclass = tclass; if (Vclass = = Object.class) This.vclass = null; else This.vclass = vclass; offset = unsafe.objectfieldoffset (field); }
Atomicintegerfieldupdate the interfaces of these updates are consistent with the atomic variables. Compareandset operation, getandset operation, etc. are provided. There is no repetition here. Take a sample to see how to use the domain updater
1. The node class has a volatile type of next field, which does not use atomicreference. Use of more lightweight volatile
2. Assume that you want to perform CAS operations on the volatile type of next. Create a Domain Updater Atomicreferencefieldupdater
Private class Node<e>{private final E item;private volatile node<e> next;public Node (E item) {This.item = Item; }}private static Atomicreferencefieldupdater<node, node> nextupdate = Atomicreferencefieldupdater.newupdater ( Node.class, Node.class, "next");
Talk about high concurrency (20) parsing java.util.concurrent each component (ii) 12 Atomic variable related classes