Atomic: Atomic variables and Atomic classes

Source: Internet
Author: User

1. What is Atomic?


The word Atomic has a relationship with atoms, which were once considered to be the smallest unit of matter. Atomic in a computer means that it cannot be divided into several parts. If a piece of code is considered Atomic, it indicates that the Code cannot be interrupted during execution. Generally, atomic commands are provided by hardware for software to implement atomic methods (after a thread enters the method, it will not be interrupted until the execution is completed)

 

On the x86 platform, the CPU provides a means to lock the bus during command execution. There is a lead on the CPU chip # HLOCK pin. If the assembly language program adds the prefix "LOCK" before a command ", the compiled machine code lowers the potential of the # HLOCK pin when the CPU executes this command until the end of this command, thereby locking the bus, in this way, other CPUs on the same bus cannot access the memory temporarily through the bus, ensuring the atomicity of this command in a multi-processor environment.

 

Ii. atomic variables in java. util. concurrent

 


Both directly and indirectly, almost all classes in the java. util. concurrent package use atomic variables instead of synchronization. Classes similar to concurrent1_queue also use atomic variables to directly implement the no-Wait algorithm, while classes similar to ConcurrentHashMap use ReentrantLock to lock when needed. Then, ReentrantLock uses atomic variables to maintain the thread queue waiting for lock.

Without JVM improvements in JDK 5.0, these classes cannot be constructed. These improvements expose (to class libraries rather than user classes) interfaces to access hardware-level synchronization primitives. Then, the atomic variable classes and other classes in java. util. concurrent make these functions public to the user class.


Java. util. concurrent. atomic class


This package provides a group of atomic classes. Its basic feature is that in a multi-threaded environment, when multiple threads simultaneously execute the methods contained by these class instances, they are exclusive, that is, when a thread enters the method, when the command is executed, it will not be interrupted by other threads, and other threads will wait until the execution of this method is complete, just like the spin lock, the JVM selects another thread from the waiting queue. This is just a logical understanding. It is actually implemented by using hardware-related commands and does not block threads (or just blocks threads at the hardware level ). The classes can be divided into four groups.

AtomicBoolean, AtomicInteger, AtomicLong, AtomicReference
AtomicIntegerArray, AtomicLongArray
AtomicLongFieldUpdater, AtomicIntegerFieldUpdater, AtomicReferenceFieldUpdater
AtomicMarkableReference, AtomicStampedReference, AtomicReferenceArray
AtomicBoolean, AtomicInteger, AtomicLong, and AtomicReference are similar.

First, the internal APIs of AtomicBoolean, AtomicInteger, AtomicLong, and AtomicReference are similar: An Example of AtomicReference


Use AtomicReference to create a thread-safe Stack

 

Java code public class writable stack <T> {
 
Private AtomicReference <Node <T> stacks = new AtomicReference <Node <T> ();
 
Public T push (T e ){
Node <T> oldNode, newNode;
While (true) {// The processing here is very special and must be the same.
OldNode = stacks. get ();
NewNode = new Node <T> (e, oldNode );
If (stacks. compareAndSet (oldNode, newNode )){
Return e;
}
}
}

Public T pop (){
Node <T> oldNode, newNode;
While (true ){
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;
}
}
}

Then follow the atomic update of the field.

AtomicIntegerFieldUpdater <T>/AtomicLongFieldUpdater <T>/AtomicReferenceFieldUpdater <T, V> is the value of the reflection-based atomic update field.

The corresponding API is also very simple, but there are some constraints.

(1) The field must be of the volatile type! What is volatile. View http://blog.csdn.net/a511596982/article/details/8201744

(2) The Field description type (modifier public/protected/default/private) is consistent with that of the caller and the operation object field. That is to say, the caller can directly operate on object fields, and then perform atomic operations through reflection. However, for the fields of the parent class, the subclass cannot directly operate, although the subclass can access the fields of the parent class.

(3) only instance variables, not class variables, that is, static keywords cannot be added.

(4) The final variable cannot be modified because the final semantics cannot be modified. In fact, the final semantics conflicts with volatile, and the two keywords cannot exist at the same time.

(5) For AtomicIntegerFieldUpdater and AtomicLongFieldUpdater, only int/long fields can be modified, and the packaging type (Integer/Long) cannot be modified ). To modify the packaging type, use AtomicReferenceFieldUpdater.

 

The operation method is described in the following example.


[Java]
Import java. util. concurrent. atomic. AtomicIntegerFieldUpdater;
 
Public class AtomicIntegerFieldUpdaterDemo {
 
Class DemoData {
Public volatile int value1 = 1;
Volatile int value2 = 2;
Protected volatile int value3 = 3;
Private volatile int value4 = 4;
}
AtomicIntegerFieldUpdater <DemoData> getUpdater (String fieldName ){
Return AtomicIntegerFieldUpdater. newUpdater (DemoData. class, fieldName );
}
Void doit (){
DemoData data = new DemoData ();
System. out. println ("1 =>" + getUpdater ("value1"). getAndSet (data, 10 ));
System. out. println ("3 =>" + getUpdater ("value2"). incrementAndGet (data ));
System. out. println ("2 =>" + getUpdater ("value3"). decrementAndGet (data ));
System. out. println ("true =>" + getUpdater ("value4"). compareAndSet (data, 4, 5 ));
}
Public static void main (String [] args ){
AtomicIntegerFieldUpdaterDemo demo = new AtomicIntegerFieldUpdaterDemo ();
Demo. doit ();
}
}

Import java. util. concurrent. atomic. AtomicIntegerFieldUpdater;

Public class AtomicIntegerFieldUpdaterDemo {

Class DemoData {
Public volatile int value1 = 1;
Volatile int value2 = 2;
Protected volatile int value3 = 3;
Private volatile int value4 = 4;
}
AtomicIntegerFieldUpdater <DemoData> getUpdater (String fieldName ){
Return AtomicIntegerFieldUpdater. newUpdater (DemoData. class, fieldName );
}
Void doit (){
DemoData data = new DemoData ();
System. out. println ("1 =>" + getUpdater ("value1"). getAndSet (data, 10 ));
System. out. println ("3 =>" + getUpdater ("value2"). incrementAndGet (data ));
System. out. println ("2 =>" + getUpdater ("value3"). decrementAndGet (data ));
System. out. println ("true =>" + getUpdater ("value4"). compareAndSet (data, 4, 5 ));
}
Public static void main (String [] args ){
AtomicIntegerFieldUpdaterDemo demo = new AtomicIntegerFieldUpdaterDemo ();
Demo. doit ();
}
}


In the preceding example, the DemoData field value3/value4 is invisible to the AtomicIntegerFieldUpdaterDemo class, so the value cannot be directly modified through reflection.

 

A <Object, Boolean> pair described by the AtomicMarkableReference class can be atomic to modify the value of an Object or Boolean. This data structure is useful in some cache or status descriptions. This structure can effectively improve throughput when modifying an Object or Boolean at the same time.

 

The AtomicStampedReference class maintains object references with an integer "sign" and can be updated in atomic mode. Compared with <Object, Boolean> of the AtomicMarkableReference class, AtomicStampedReference maintains a data structure similar to <Object, int>, which is actually a concurrent count of objects (references. However, unlike AtomicInteger, this data structure can carry an Object reference and perform atomic operations on this Object and the count at the same time.

The "ABA problem" will be mentioned at the end of this article, while AtomicMarkableReference/AtomicStampedReference is useful in solving the "ABA problem.

Iii. Role of the Atomic class


This makes operations on a single data atomic.
Use the Atomic class to build complex code without blocking
Access to two or more atomic variables (or perform two or more operations on a single atomic variable) is generally considered to require synchronization, so that these operations can be used as an atomic unit.
No lock and no waiting Algorithm


CAS (compare and swap)-Based Concurrency Algorithms are called non-locking algorithms, because threads do not have to wait for locking (sometimes known as mutex or key part, depending on the thread platform terminology ). No matter whether the CAS operation succeeds or fails, in any case, it is completed within a predictable period of time. If CAS fails, the caller can retry the CAS operation or take other appropriate operations.


If each thread continues to operate at any delay (or even failure) of other threads, it can be said that the algorithm does not have to wait. In contrast, the non-locking algorithm requires that only one thread always perform operations. (Another definition without waiting is to ensure that each thread correctly calculates its own operations in its limited steps, regardless of the operation, timing, crossover, or speed of other threads. This limit can be a function of the number of threads in the system. For example, if there are 10 threads, each thread executes CasCounter once. increment () operation. In the worst case, each thread must retry up to nine times to complete the increase .)

Over the past 15 years, people have done a lot of research on the no-wait and no-lock algorithm (also known as the no-Blocking Algorithm). Many people have found a non-blocking algorithm in the general data structure. Non-Blocking Algorithms are widely used in operating systems and JVM-level tasks such as thread and process scheduling. Although their implementation is complicated, they have many advantages over lock-based alternative algorithms: they can avoid risks such as priority inversion and deadlock, and the competition is relatively cheap, coordination takes place at a finer granularity level and allows a higher level of parallel mechanism.

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.