java.util.concurrent.atomic Atomic Operation Class Pack
=====
java.util.concurrent.atomic Atomic Operation Class Pack
This package provides a set of atomic variable classes. The basic feature is that in a multithreaded environment, when there are multiple threads executing the methods contained by instances of these classes at the same time, there is exclusivity, that is, when a thread enters the method and executes the instruction, it is not interrupted by another thread, and the other thread is like a spin lock until the method executes. It is only a logical understanding that the JVM chooses a second thread from the waiting queue to enter. It is actually implemented with hardware-related instructions that do not block threads (or simply block at the hardware level). You can manipulate basic data, basic data in an array, and basic data in a class. The atomic variable class is equivalent to a generalized volatile variable that supports both atomic and conditional read-write operations.
The classes in Java.util.concurrent.atomic can be divided into 4 groups:
- Scalar class (scalar): atomicboolean,atomicinteger,atomiclong,atomicreference
- Array class: Atomicintegerarray,atomiclongarray,atomicreferencearray
- Updater class: Atomiclongfieldupdater,atomicintegerfieldupdater,atomicreferencefieldupdater
- Compound Variable class: Atomicmarkablereference,atomicstampedreference
The first group of atomicboolean,atomicinteger,atomiclong,atomicreference these four basic types is used to deal with Boolean, Integer, Long Integer, object four kinds of data, its internal implementation is not simple to use synchronized, It is a more efficient way of CAS (compare and swap) + volatile and native methods, which avoids the high overhead of synchronized and greatly improves execution efficiency. The implementation fragments such as Atomicinteger are:
Java code
- Private Static final unsafe unsafe = unsafe.getunsafe ();
- Private volatile int value;
- Public final int get () {
- return value;
- }
- Public final void set (int newvalue) {
- value = newvalue;
- }
- Public Final boolean compareandset (int expect, int update) {
- return Unsafe.compareandswapint (this, Valueoffset, expect, update);
- }
- Constructors (two constructors)
- Default constructor: The initialized data is False,0,0,null
- Parameter constructor: Data with parameters initialized
- Set () and Get () methods: Atomic data can be set and obtained atomically. Similar to volatile, ensuring that data is set or read in main memory
- void set () and void Lazyset (): Set to the given value, modify the original value directly, Lazyset delay sets the value of the variable, which is equivalent to the set () method, but because the field is volatile type, Therefore, the modification of the secondary field has a slight performance delay (although negligible) than the normal field (non-volatile field), so this method is useful if you do not want to read the new value of the setting immediately, allowing the value to be modified in the background.
- Getandset () method
- The atom sets the variable to the new data while returning the previous old data
- It is essentially a get () operation and then a set () operation. Although these 2 operations are atomic, they are not atomic when they are merged together. At the level of Java's source program, it is not possible to do this without relying on the synchronized mechanism. You can only rely on the native method.
Java code
- Public Final int getandset (int newvalue) {
- for (;;) {
- int current = get ();
- if (Compareandset (current, newvalue))
- return current;
- }
- }
- Compareandset () and Weakcompareandset () methods
- Both of these methods are conditional modifier methods. These 2 methods accept 2 parameters, one is the expected data (expected), the other is the new data, and if the data in the atomic is consistent with the expected data, the new data is set to the atomic data, which returns true to indicate success, otherwise it is not set and returns false. The JSR specification reads and conditionally writes variables but does not create any happen-before sort, and therefore does not provide a weakcompareandset Any guarantees related to previous or subsequent read or write operations of any variables outside the target. The main idea is that when calling Weakcompareandset, there is no guarantee that no happen-before will occur (that is, there may be a command reordering that causes this operation to fail). However, from the Java source, in fact, this method does not implement the requirements of the JSR specification, the final effect and compareandset are equivalent, all call the Unsafe.compareandswapint () to complete the operation.
Java code
- public final boolean compareandset (int expect, int update) {
- return unsafe.compareandswapint (this, valueoffset, expect, update);
- }
- public final boolean weakcompareandset (int expect, int update) {
- return unsafe.compareandswapint (this, valueoffset, expect, update);
- }
- For Atomicinteger, Atomiclong also offers some special methods.
Getandincrement (): atomically adds 1 to the current value, which is equivalent to a thread-safe i++ operation.
Incrementandget (): atomically adds 1 to the current value, which is equivalent to a thread-safe ++i operation.
Getanddecrement (): atomically minimizes the current value by 1, which is equivalent to a thread-safe i--operation.
Decrementandget (): atomically converts the current value by 1, which is equivalent to a thread-safe-I operation.
Addandget (): atomically adds the given value to the current value, which is actually equal to the thread-safe i =i+delta operation.
Getandadd (): atomically adds the given value to the current value, which is equivalent to a thread-safe t=i;i+=delta;return t;
To achieve some addition, subtract atomic operations. (Note that the-I, ++i is not an atomic operation, it contains 3 steps: The first step, read I; second step, add 1 or minus 1; step three: Write back memory)
Creating a thread-safe stack using atomicreference
Java code
- Package thread;
- Import java.util.concurrent.atomic.AtomicReference;
- Public class Concurrentstack<t> {
- private atomicreference<node<t>> stacks = new atomicreference<node<t>> ();
- Public t push (t e) {
- Node<t> OldNode, NewNode;
- for (;;) { //The handling here is very special and must be so.
- OldNode = Stacks.get ();
- NewNode = New Node<t> (E, OldNode);
- if (Stacks.compareandset (OldNode, NewNode)) {
- return e;
- }
- }
- }
- Public T Pop () {
- Node<t> OldNode, NewNode;
- for (;;) {
- OldNode = Stacks.get ();
- NewNode = Oldnode.next;
- if (Stacks.compareandset (OldNode, NewNode)) {
- return oldnode.object;
- }
- }
- }
- private Static final class Node<t> {
- private T object;
- private node<t> Next;
- Private Node (T object, node<t> next) {
- This.object = object;
- This.next = next;
- }
- }
- }
Although the scalar class of atoms extends the number class, it does not extend some basic types of wrapper classes, such as Integer or long, and in fact they cannot extend: The wrapper class of the basic type is not modifiable, and the atomic variable class can be modified. The hashcode or Equals method is not redefined in the atomic variable class, and each instance is different, and they should not be used as a key value based on a hash container.
The second set of Atomicintegerarray,atomiclongarray and the Atomicreferencearray class further extended atomic operations, providing support for these types of arrays. These classes are also noticeable in providing volatile access semantics for their array elements, which is not supported for normal arrays.
They do not internally maintain a valatile variable like Atomicinteger, but are all implemented by the native method, as follows
The implementation fragment of Atomicintegerarray:
Java code
- Private Static final unsafe unsafe = unsafe.getunsafe ();
- Private static final int base = Unsafe.arraybaseoffset (int[]. Class);
- Private static final int scale = Unsafe.arrayindexscale (int[]. Class);
- Private final int[] array;
- Public final int get (int i) {
- return Unsafe.getintvolatile (array, Rawindex (i));
- }
- Public final void set (int i, int newvalue) {
- Unsafe.putintvolatile (Array, Rawindex (i), newvalue);
- }
The third set of Atomiclongfieldupdater,atomicintegerfieldupdater,atomicreferencefieldupdater-based utilities that can specify volatile the specified class field for atomic updates. The API is very simple, but there are some constraints:
(1) The field must be of type volatile
(2) The description type (modifier public/protected/default/private) of the field is consistent with the caller's relationship to the Action Object field. That is, the caller is able to manipulate the object field directly, then the atomic operation can be reflected. However, for a field of the parent class, the subclass cannot be manipulated directly, although the subclass can access the fields of the parent class.
(3) can only be an instance variable, not a class variable, that is, the static keyword cannot be added.
(4) can only be modifiable variables, cannot make final variables, because final semantics is not modifiable. There is actually a conflict between final semantics and volatile, and these two keywords cannot exist at the same time.
(5) for Atomicintegerfieldupdater and Atomiclongfieldupdater only fields of type Int/long can be modified, their wrapper type (Integer/long) cannot be modified. If you want to modify the wrapper type, you need to use Atomicreferencefieldupdater.
netty5.0 The total number of bytes sent in class Channeloutboundbuffer statistics, because the use of volatile variables are not enough, so use atomicintegerfieldupdater to achieve, see the following code:
Java code
- Defined
- private static final atomiclongfieldupdater<channeloutboundbuffer> Total_pending_size_updater =
- Atomiclongfieldupdater.newupdater (Channeloutboundbuffer. Class, "totalpendingsize");
- Private volatile long totalpendingsize;
- Use
- long oldValue = totalpendingsize;
- Long newwritebuffersize = oldValue + size;
- while (!total_pending_size_updater.compareandset (this, OldValue, newwritebuffersize)) {
- OldValue = totalpendingsize;
- Newwritebuffersize = oldValue + size;
- }
Concurrent Java.util.concurrent.atomic Atomic Operation class Package