First, what is atomic?
The word atomic has something to do with atoms, which were thought to be the smallest unit of matter. The atomic in a computer means that it cannot be divided into parts. If a piece of code is considered atomic, it means that the code cannot be interrupted during execution. In general, atomic instructions are provided by the hardware for the software to implement the Atomic method (after a thread enters the method, it is not interrupted until it completes)
On the x86 platform, the CPU provides a means of locking the bus during instruction execution. The CPU chip has a lead #hlock pin, if the assembly language program in a command prefix "LOCK", after the assembly of the machine code so that the CPU in the execution of this instruction at the time of the #hlock pin to pull down, continue to the end of this instruction to release, So that the bus lock, so that the other CPU on the same bus temporarily can not access the memory through the bus, to ensure that this instruction in the multi-processor environment of atomicity.
Two, JDK1.5 's Atom pack: java.util.concurrent.atomic
This package provides a set of atomic 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). The classes can be divided into 4 groups
- Atomicboolean,atomicinteger,atomiclong,atomicreference
- Atomicintegerarray,atomiclongarray
- Atomiclongfieldupdater,atomicintegerfieldupdater,atomicreferencefieldupdater
- Atomicmarkablereference,atomicstampedreference,atomicreferencearray
The role of the Atomic class
- Enables the manipulation of a single data to achieve atomicity
- Use the atomic class to build complex, block-free code
- Access to 2 or more of the atomic variables (or 2 or more 2 operations on a single atomic variable) is generally considered to be synchronous, so that these operations can be used as an atomic unit.
2.1 Atomicboolean, Atomicinteger, Atomiclong, atomicreference
These four basic types are used to handle Boolean, Integer, Long Integer, and object four kinds of data.
- 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
- 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.
- 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.
- For Atomicinteger, Atomiclong also offers some special methods. Getandincrement (), Incrementandget (), Getanddecrement (), Decrementandget (), Addandget (), Getandadd () 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)
- Here is a comparison test, we write a synchronized method and a Atomicinteger method to test, intuitively feel the difference in performance
Packagezl.study.concurrency;ImportJava.util.concurrent.atomic.AtomicInteger; Public classAtomicintegercomparetest {Private intvalue; PublicAtomicintegercomparetest (intvalue) { This. Value =value; } Public synchronized intIncrease () {returnvalue++; } Public Static voidMain (String args[]) {LongStart =System.currenttimemillis (); Atomicintegercomparetest Test=NewAtomicintegercomparetest (0); for(inti=0;i< 1000000;i++) {test.increase (); } LongEnd =System.currenttimemillis (); System.out.println ("Time Elapse:" + (End-start)); LongStart1 =System.currenttimemillis (); Atomicinteger Atomic=NewAtomicinteger (0); for(inti=0;i< 1000000;i++) {atomic.incrementandget (); } LongEnd1 =System.currenttimemillis (); System.out.println ("Time Elapse:" + (End1-Start1)); }}
Results
Time elapse:31
Time Elapse:16
It is not difficult to see that the local CAS performance by JNI is far beyond the synchronized keyword
Java Thread: Atomic (Atomic)