


Java concurrent programming (8) Atomic variables and non-blocking synchronization mechanism
Atomic variables and non-blocking synchronization mechanism
1. Disadvantages of locks
1. Under multi-threading: there is a lot of overhead in the process of lock suspension and recovery ( Modern jvm will determine when to use suspend and when to spin and wait)
2.volatile: lightweight level synchronization mechanism, but cannot be used to build atomic composite operations
Therefore : There needs to be a way to manage competition between threads with a finer granularity, similar to the volatile mechanism, while also supporting atomic update operations
2. CAS
Exclusive locking is a pessimistic technique - it assumes the worst case scenario, so each thread is exclusive
And CAS compare and swap: compareAndSwap/Set(A,B): We think the value in memory It is A. If it is A, modify it to B, otherwise no operation will be performed; return the original value in the memory or whether the modification is successful
For example: simulate CAS operation
//模拟的CASpublic class SimulatedCAS {private int value;public synchronized int get() {return value; }//CAS操作public synchronized int compareAndSwap(int expectedValue, int newValue) {int oldValue = value;if (oldValue == expectedValue) { value = newValue; }return oldValue; }public synchronized boolean compareAndSet(int expectedValue, int newValue) {return (expectedValue == compareAndSwap(expectedValue, newValue)); } }//典型使用场景public class CasCounter {private SimulatedCAS value;public int getValue() {return value.get(); }public int increment() {int v;do { v = value.get(); } while { (v != value.compareAndSwap(v, v + 1)); }return v + 1; } }
JAVA provides CAS operations
Atomic state class: CAS method of AtomicXXX
JAVA7/8: Map operations: putIfAbsent, computerIfAbsent, computerIfPresent.. .......
3. Atomic variable class
AtomicRefence atomic update object can be a custom object; such as:
public class CasNumberRange {private static class IntPair {// INVARIANT: lower <= upperfinal int lower; //将值定义为不可变域final int upper; //将值定义为不可变域public IntPair(int lower, int upper) {this.lower = lower;this.upper = upper; } }private final AtomicReference<IntPair> values = new AtomicReference<IntPair>(new IntPair(0, 0)); //封装对象public int getLower() {return values.get().lower; }public int getUpper() {return values.get().upper; }public void setLower(int i) {while (true) { IntPair oldv = values.get();if (i > oldv.upper) {throw new IllegalArgumentException("Can't set lower to " + i + " > upper"); } IntPair newv = new IntPair(i, oldv.upper); //属性为不可变域,则每次更新新建对象if (values.compareAndSet(oldv, newv)) { //原子更新,如果在过程中有线程修改了,则其他线程不会更新成功,因为oldv与内存处值就不同了return; } } }//同上public void setUpper(int i) {while (true) { IntPair oldv = values.get();if (i < oldv.lower)throw new IllegalArgumentException("Can't set upper to " + i + " < lower"); IntPair newv = new IntPair(oldv.lower, i);if (values.compareAndSet(oldv, newv))return; } } }
Performance issue: Using atomic variables is faster than using locks under medium and low concurrency (competition). Generally, it is faster than locking speed
4. Non-blocking algorithm
Non-blocking algorithm can be used in many common data structures
Non-blocking algorithm: In multi-threading, there is uncertainty about whether the work will be successful and it needs to be executed in a loop. And perform atomic operations through CAS
1. The above CasNumberRange
2. Non-blocking algorithm of the stack: only save the head pointer, only one state
//栈实现的非阻塞算法:单向链表public class ConcurrentStack <E> { AtomicReference<Node<E>> top = new AtomicReference<Node<E>>();public void push(E item) { Node<E> newHead = new Node<E>(item); Node<E> oldHead;do { oldHead = top.get(); newHead.next = oldHead; } while (!top.compareAndSet(oldHead, newHead));//CAS操作:原子更新操作,循环判断,非阻塞 }public E pop() { Node<E> oldHead; Node<E> newHead;do { oldHead = top.get();if (oldHead == null) {return null; } newHead = oldHead.next; } while (!top.compareAndSet(oldHead, newHead));//CAS操作:原子更新操作,循环判断,非阻塞return oldHead.item; }private static class Node <E> {public final E item;public Node<E> next;public Node(E item) {this.item = item; } } }
3. Non-blocking algorithm for linked lists: fast access to the head and tail, saving two states, more complex
public class LinkedQueue <E> {private static class Node <E> {final E item;final AtomicReference<LinkedQueue.Node<E>> next;public Node(E item, LinkedQueue.Node<E> next) {this.item = item;this.next = new AtomicReference<LinkedQueue.Node<E>>(next); } }private final LinkedQueue.Node<E> dummy = new LinkedQueue.Node<E>(null, null);private final AtomicReference<LinkedQueue.Node<E>> head = new AtomicReference<LinkedQueue.Node<E>>(dummy);private final AtomicReference<LinkedQueue.Node<E>> tail = new AtomicReference<LinkedQueue.Node<E>>(dummy); //保存尾节点public boolean put(E item) { LinkedQueue.Node<E> newNode = new LinkedQueue.Node<E>(item, null);while (true) { LinkedQueue.Node<E> curTail = tail.get(); LinkedQueue.Node<E> tailNext = curTail.next.get();if (curTail == tail.get()) {if (tailNext != null) {// 处于中间状态,更新尾节点为当前尾节点的next tail.compareAndSet(curTail, tailNext); } else {// 将当前尾节点的next 设置为新节点:链表if (curTail.next.compareAndSet(null, newNode)) {/** * 此处即为中间状态,虽然在这里进行了两次原子操作,整体不是原子的,但是通过算法保证了安全: * 原因是处于中间状态时,如果有其他线程进来操作,则上面那个if将执行; * 上面if的操作是来帮助当前线程完成更新尾节点操作,而当前线程的更新就会失败返回,最终则是更新成功 */// 链接成功,尾节点已经改变,则将当前尾节点,设置为新节点 tail.compareAndSet(curTail, newNode);return true; } } } } } }
3. Atomic domain updater
The above logic implements the non-blocking algorithm of the linked list, using Node to save the head node and tail node
The actual ConcurrentLinkedQueue is based on Reflected AtomicReferenceFiledUpdater to wrap Node
5. ABA problem
Issues that are likely to occur in CAS operations:
Judgment value Whether it is A, if so, continue the update operation and change it to B;
But if a thread changes the value A to C, and then changes it back to A, at this time, the original thread will judge that A=A and successfully execute the update Operation;
If you change A to C and then change it back to A, it also needs to be regarded as a change, and the algorithm needs to be optimized
Solution: Add a version number every time it is updated All operations must update the version number, even if the value is the same
The above is the detailed content of Java concurrent programming (8) Atomic variables and non-blocking synchronization mechanism. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



Java 8 introduces the Stream API, providing a powerful and expressive way to process data collections. However, a common question when using Stream is: How to break or return from a forEach operation? Traditional loops allow for early interruption or return, but Stream's forEach method does not directly support this method. This article will explain the reasons and explore alternative methods for implementing premature termination in Stream processing systems. Further reading: Java Stream API improvements Understand Stream forEach The forEach method is a terminal operation that performs one operation on each element in the Stream. Its design intention is

Python is an ideal programming introduction language for beginners through its ease of learning and powerful features. Its basics include: Variables: used to store data (numbers, strings, lists, etc.). Data type: Defines the type of data in the variable (integer, floating point, etc.). Operators: used for mathematical operations and comparisons. Control flow: Control the flow of code execution (conditional statements, loops).

Pythonempowersbeginnersinproblem-solving.Itsuser-friendlysyntax,extensivelibrary,andfeaturessuchasvariables,conditionalstatements,andloopsenableefficientcodedevelopment.Frommanagingdatatocontrollingprogramflowandperformingrepetitivetasks,Pythonprovid

C is an ideal choice for beginners to learn system programming. It contains the following components: header files, functions and main functions. A simple C program that can print "HelloWorld" needs a header file containing the standard input/output function declaration and uses the printf function in the main function to print. C programs can be compiled and run by using the GCC compiler. After you master the basics, you can move on to topics such as data types, functions, arrays, and file handling to become a proficient C programmer.

C is an ideal language for beginners to learn programming, and its advantages include efficiency, versatility, and portability. Learning C language requires: Installing a C compiler (such as MinGW or Cygwin) Understanding variables, data types, conditional statements and loop statements Writing the first program containing the main function and printf() function Practicing through practical cases (such as calculating averages) C language knowledge

Java is a popular programming language that can be learned by both beginners and experienced developers. This tutorial starts with basic concepts and progresses through advanced topics. After installing the Java Development Kit, you can practice programming by creating a simple "Hello, World!" program. After you understand the code, use the command prompt to compile and run the program, and "Hello, World!" will be output on the console. Learning Java starts your programming journey, and as your mastery deepens, you can create more complex applications.

Capsules are three-dimensional geometric figures, composed of a cylinder and a hemisphere at both ends. The volume of the capsule can be calculated by adding the volume of the cylinder and the volume of the hemisphere at both ends. This tutorial will discuss how to calculate the volume of a given capsule in Java using different methods. Capsule volume formula The formula for capsule volume is as follows: Capsule volume = Cylindrical volume Volume Two hemisphere volume in, r: The radius of the hemisphere. h: The height of the cylinder (excluding the hemisphere). Example 1 enter Radius = 5 units Height = 10 units Output Volume = 1570.8 cubic units explain Calculate volume using formula: Volume = π × r2 × h (4

Spring Boot simplifies the creation of robust, scalable, and production-ready Java applications, revolutionizing Java development. Its "convention over configuration" approach, inherent to the Spring ecosystem, minimizes manual setup, allo
