Table of Contents
1. synchronized: the most primitive but still efficient synchronization mechanism
advantage:
shortcoming:
2. Explicit lock: more flexible control
Key Advantages:
Recommended usage:
3. Lock-Free algorithm: non-blocking concurrency based on CAS
CAS Principle:
Example: Atomic integer counter
ABA issues with CAS
4. Advanced Lock-Free Data Structure
1. ConcurrentLinkedQueue
2. AtomicIntegerFieldUpdater / AtomicReferenceFieldUpdater
3. LongAdder vs AtomicLong
5. Implement a simple Lock-Free stack (lockless stack)
Summary: The evolution logic from synchronized to Lock-Free
Recommendations for use
Home Java javaTutorial Advanced Java Multithreading: from synchronized to Lock-Free Algorithms

Advanced Java Multithreading: from synchronized to Lock-Free Algorithms

Jul 27, 2025 am 01:13 AM

synchronized is the earliest synchronization mechanism in Java. It is simple and easy to use and has good performance after optimization, but lacks flexibility; 2. ReentrantLock provides advanced functions such as interruptibility, reentrant, and support fairness, which is suitable for scenarios that require fine control; 3. The lock-free algorithm implements non-blocking concurrency based on CAS, such as AtomicLong, LongAdder and ConcurrentLinkedQueue, which performs better in a high-competitive environment, but needs to deal with ABA problems and CPU spin overhead; ultimately, appropriate strategies should be selected based on the concurrency strength: synchronized for low-competitive competition, and ReentrantLock for control, and lock-free structure for high-concurrency scenarios, so as to achieve the evolution from basic synchronization to high-performance concurrency.

Advanced Java Multithreading: from synchronized to Lock-Free Algorithms

Java's multi-threaded programming has gradually evolved from the early synchronized keyword to the more flexible Lock framework, and then to the lock-free (Lock-Free) algorithm widely used in high-performance scenarios today. Mastering this evolution path will not only help to write more efficient concurrent programs, but also provide a deep understanding of the concurrency mechanisms at the modern JVM and hardware levels.

Advanced Java Multithreading: from synchronized to Lock-Free Algorithms

The following is an analysis from three levels: synchronized → explicit lock ( ReentrantLock ) → lock-free algorithm (Lock-Free), which takes you from basic to advanced.


1. synchronized: the most primitive but still efficient synchronization mechanism

synchronized is the earliest thread synchronization keyword provided by Java. It can be used in method or code blocks to ensure that only one thread can enter the critical area at the same time.

Advanced Java Multithreading: from synchronized to Lock-Free Algorithms
 public synchronized void increment() {
    count ;
}

advantage:

  • Simple and easy to use, JVM automatically manages the acquisition and release of locks.
  • After a lot of optimizations (biased locks, lightweight locks, lock expansion, etc.) after JDK 1.6, the performance has been greatly improved.

shortcoming:

  • It is not interruptible, and the interrupt cannot be responded to when the thread is blocked.
  • Cannot try to add lock (no tryLock).
  • Fairness control is not supported.
  • The locking particle size is relatively coarse and has poor flexibility.

Nevertheless, synchronized is still preferred in most ordinary concurrency scenarios , because its performance is already very close to explicit locking and is not prone to errors.


2. Explicit lock: more flexible control

Java 5 introduces the java.util.concurrent.locks.Lock interface, the most commonly used is ReentrantLock , which provides richer functions than synchronized .

Advanced Java Multithreading: from synchronized to Lock-Free Algorithms
 private final ReentrantLock lock = new ReentrantLock();

public void increment() {
    lock.lock();
    try {
        count ;
    } finally {
        lock.unlock();
    }
}

Key Advantages:

  • Support interruptible lock acquisition ( lockInterruptibly() )
  • Supports trying to add locks ( tryLock() ) to avoid infinite waiting
  • Support fair locks ( true is passed in during construction) to reduce thread hunger
  • Fine-grained conditional control ( Condition )
  • Use ReentrantLock when you need timeout attempts, interrupt responses, or fairness.
  • It must be used in conjunction with try-finally , otherwise deadlocks are prone to occur.

But note: explicit locks are still "blocking" . If the thread cannot get the lock, it will be suspended, and context switching will bring overhead.


3. Lock-Free algorithm: non-blocking concurrency based on CAS

True high-performance concurrency, especially in high-competitive scenarios (such as high-frequency trading, high-concurrency counters, lock-free queues), needs to get rid of the concept of "lock" and turn to the Lock-Free or Wait-Free algorithm.

Its core is CAS (Compare-And-Swap) operation, provided by Unsafe class, encapsulated in Java through java.util.concurrent.atomic package.

CAS Principle:

 // Pseudocode: update to update only if the current value is equal to expect
boolean compareAndSet(int expect, int update);

Example: Atomic integer counter

 private final AtomicLong counter = new AtomicLong(0);

public void increment() {
    counter.incrementAndGet(); // Internal based CAS loop}

ABA issues with CAS

CAS only compares whether the values are equal, and does not care whether the middle has been modified. For example:

  • Thread 1 reads the value A
  • Thread 2 Turn A → B → A
  • Thread 1 executes CAS(A, new_value), successfully, but the intermediate state has been tampered with

Solution : Use AtomicStampedReference to introduce a version number (timestamp) to distinguish real changes.

 AtomicStampedReference<Integer> ref = new AtomicStampedReference<>(100, 0);

int stamp = ref.getStamp();
Integer value = ref.getReference();
if (ref.compareAndSet(value, newValue, stamp, stamp 1)) {
    // Updated successfully}

4. Advanced Lock-Free Data Structure

JDK provides some high-performance containers based on lock-free algorithms:

1. ConcurrentLinkedQueue

  • Lockless thread-safe queue
  • Implement offer() and poll() based on CAS
  • Suitable for high concurrency producers-consumer scenarios

2. AtomicIntegerFieldUpdater / AtomicReferenceFieldUpdater

  • Can perform atomic operations on the volatile field of a normal object
  • Avoid creating AtomicInteger objects for each field, saving memory
 public class Task {
    volatile int state;
    static final AtomicIntegerFieldUpdater<Task> updater =
        AtomicIntegerFieldUpdater.newUpdater(Task.class, "state");

    public boolean setStateIf(int expected, int newValue) {
        return updater.compareAndSet(this, expected, newValue);
    }
}

3. LongAdder vs AtomicLong

  • In high concurrency accumulation scenarios, LongAdder performance is far superior AtomicLong
  • Principle: segmented accumulation (segment of segmented locking idea of ConcurrentHashMap), final summary
 private final LongAdder adder = new LongAdder();

public void increment() {
    adder.increment(); // There are fewer conflicts under high concurrency}

public long getTotal() {
    return adder.sum(); // Summarize the values of all segments}

5. Implement a simple Lock-Free stack (lockless stack)

 public class LockFreeStack<T> {
    private final AtomicReference<Node<T>> top = new AtomicReference<>();

    private static class Node<T> {
        final T value;
        final Node<T> next;

        Node(T value, Node<T> next) {
            this.value = value;
            this.next = next;
        }
    }

    public void push(T value) {
        Node<T> newHead = new Node<>(value, null);
        Node<T> currentHead;
        do {
            currentHead = top.get();
            newHead = new Node<>(value, currentHead);
        } while (!top.compareAndSet(currentHead, newHead));
    }

    public T pop() {
        Node<T> currentHead;
        Node<T> newHead;
        do {
            currentHead = top.get();
            if (currentHead == null) return null;
            newHead = currentHead.next;
        } while (!top.compareAndSet(currentHead, newHead));
        return currentHead.value;
    }
}

This stack uses AtomicReference and CAS to implement push/pop, and there is no lock in the whole process, but please note:

  • Loop retry (spin) may consume CPU
  • Not suitable for long-term operation

Summary: The evolution logic from synchronized to Lock-Free

characteristic synchronized ReentrantLock Lock-Free
Ease of use ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐
Performance (low competition) high high Extremely high
Performance (high competition) Significant decline Significant decline Still efficient
Interruptible ✅(Non-blocking)
Fairness N/A
ABA Questions not applicable not applicable Need to be processed

Recommendations for use

  • synchronized is preferred for normal scenarios, which is fast and safe enough.
  • Use ReentrantLock when timeout, interrupt, and fairness are required.
  • High concurrency counting and status update use AtomicXXX or LongAdder .
  • When building high-performance queues, stacks, etc., consider ConcurrentLinkedQueue or handwritten CAS structure.
  • Note: No lock ≠ no cost. CAS failed retry may cause CPU waste and need to be evaluated in combination with scenarios.

Basically that's it. By mastering these levels, you can choose the most appropriate synchronization strategy at different concurrency intensity, from "knowing to use locks" to "knowing concurrency".

The above is the detailed content of Advanced Java Multithreading: from synchronized to Lock-Free Algorithms. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undress AI Tool

Undress AI Tool

Undress images for free

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Hot Topics

PHP Tutorial
1510
276
How to handle transactions in Java with JDBC? How to handle transactions in Java with JDBC? Aug 02, 2025 pm 12:29 PM

To correctly handle JDBC transactions, you must first turn off the automatic commit mode, then perform multiple operations, and finally commit or rollback according to the results; 1. Call conn.setAutoCommit(false) to start the transaction; 2. Execute multiple SQL operations, such as INSERT and UPDATE; 3. Call conn.commit() if all operations are successful, and call conn.rollback() if an exception occurs to ensure data consistency; at the same time, try-with-resources should be used to manage resources, properly handle exceptions and close connections to avoid connection leakage; in addition, it is recommended to use connection pools and set save points to achieve partial rollback, and keep transactions as short as possible to improve performance.

Java Virtual Threads Performance Benchmarking Java Virtual Threads Performance Benchmarking Jul 21, 2025 am 03:17 AM

Virtual threads have significant performance advantages in highly concurrency and IO-intensive scenarios, but attention should be paid to the test methods and applicable scenarios. 1. Correct tests should simulate real business, especially IO blocking scenarios, and use tools such as JMH or Gatling to compare platform threads; 2. The throughput gap is obvious, and it can be several times to ten times higher than 100,000 concurrent requests, because it is lighter and efficient in scheduling; 3. During the test, it is necessary to avoid blindly pursuing high concurrency numbers, adapting to non-blocking IO models, and paying attention to monitoring indicators such as latency and GC; 4. In actual applications, it is suitable for web backend, asynchronous task processing and a large number of concurrent IO scenarios, while CPU-intensive tasks are still suitable for platform threads or ForkJoinPool.

how to set JAVA_HOME environment variable in windows how to set JAVA_HOME environment variable in windows Jul 18, 2025 am 04:05 AM

TosetJAVA_HOMEonWindows,firstlocatetheJDKinstallationpath(e.g.,C:\ProgramFiles\Java\jdk-17),thencreateasystemenvironmentvariablenamedJAVA_HOMEwiththatpath.Next,updatethePATHvariablebyadding%JAVA\_HOME%\bin,andverifythesetupusingjava-versionandjavac-v

Java Microservices Service Mesh Integration Java Microservices Service Mesh Integration Jul 21, 2025 am 03:16 AM

ServiceMesh is an inevitable choice for the evolution of Java microservice architecture, and its core lies in decoupling network logic and business code. 1. ServiceMesh handles load balancing, fuse, monitoring and other functions through Sidecar agents to focus on business; 2. Istio Envoy is suitable for medium and large projects, and Linkerd is lighter and suitable for small-scale trials; 3. Java microservices should close Feign, Ribbon and other components and hand them over to Istiod for discovery and communication; 4. Ensure automatic injection of Sidecar during deployment, pay attention to traffic rules configuration, protocol compatibility, and log tracking system construction, and adopt incremental migration and pre-control monitoring planning.

Implement a linked list in Java Implement a linked list in Java Jul 20, 2025 am 03:31 AM

The key to implementing a linked list is to define node classes and implement basic operations. ①First create the Node class, including data and references to the next node; ② Then create the LinkedList class, implementing the insertion, deletion and printing functions; ③ Append method is used to add nodes at the tail; ④ printList method is used to output the content of the linked list; ⑤ deleteWithValue method is used to delete nodes with specified values and handle different situations of the head node and the intermediate node.

Java Security for Server-Side Template Injection Java Security for Server-Side Template Injection Jul 16, 2025 am 01:15 AM

Preventing server-side template injection (SSTI) requires four aspects: 1. Use security configurations, such as disabling method calls and restricting class loading; 2. Avoid user input as template content, only variable replacement and strictly verify input; 3. Adopt sandbox environments, such as Pebble, Mustache or isolating rendering context; 4. Regularly update the dependent version and review the code logic to ensure that the template engine is configured reasonably and prevent the system from being attacked due to user-controllable templates.

Advanced Java Collection Framework Optimizations Advanced Java Collection Framework Optimizations Jul 20, 2025 am 03:48 AM

To improve the performance of Java collection framework, we can optimize from the following four points: 1. Choose the appropriate type according to the scenario, such as frequent random access to ArrayList, quick search to HashSet, and concurrentHashMap for concurrent environments; 2. Set capacity and load factors reasonably during initialization to reduce capacity expansion overhead, but avoid memory waste; 3. Use immutable sets (such as List.of()) to improve security and performance, suitable for constant or read-only data; 4. Prevent memory leaks, and use weak references or professional cache libraries to manage long-term survival sets. These details significantly affect program stability and efficiency.

Building RESTful APIs in Java with Jakarta EE Building RESTful APIs in Java with Jakarta EE Jul 30, 2025 am 03:05 AM

SetupaMaven/GradleprojectwithJAX-RSdependencieslikeJersey;2.CreateaRESTresourceusingannotationssuchas@Pathand@GET;3.ConfiguretheapplicationviaApplicationsubclassorweb.xml;4.AddJacksonforJSONbindingbyincludingjersey-media-json-jackson;5.DeploytoaJakar

See all articles