Java 线程同步-04:lock 机制

前言

Java的Lock机制是Java并发编程(JDK 1.5+)中用于控制多个线程访问共享资源的核心工具。它位于java.util.concurrent.locks包下,提供了比传统的synchronized关键字更灵活、更强大的锁定操作。

本文主要介绍以 ReentrantLockReentrantReadWriteLock 为代表的lock机制,文章内容包含一下几个:Java Lock 类继承关系、Lock 使用代码示例、Lock 原理。

类结构

Java的lock机制源头可以从Lock接口说起,这是lock机制的抽象类,规定了锁的相关协议,它定义了锁的获取和释放方法。相比于synchronized(隐式获取/释放锁),Lock需要显式地获取和释放锁。

Lock接口核心方法:

java 复制代码
public interface Lock {
    // 1. 基本锁操作
    void lock();
    void unlock();
    
    // 2. 可中断锁
    void lockInterruptibly() throws InterruptedException;
    
    // 3. 尝试获取锁
    boolean tryLock();
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
    
    // 4. 条件变量
    Condition newCondition();
}

Java同步机制里面涉及的接口层主要有下面三个核心接口:

  1. Lock 接口 - 所有锁的顶级接口,定义了 lock()、unlock() 等基本方法
  2. ReadWriteLock 接口 - 读写锁接口,定义了读锁和写锁的获取方法
  3. Condition 接口 - 条件变量接口,用于线程间的等待/通知机制

对上面几个接口类常用的主要有几个实现类:

  1. ReentrantLock:实现了 Lock 接口内部包含 Sync 同步器
  2. ReentrantReadWriteLock:实现了 ReadWriteLock 接口 内部包含 Sync、ReadLock、WriteLock几个内部类
  3. ConditionObject:实现了 Condition 接口,是 AQS 的内部类

简化版继承结构类图UML:

flowchart TD %% 接口层 Lock[Lock接口] --> RL[ReentrantLock] Lock --> RLock[ReadLock] Lock --> WLock[WriteLock] RWL[ReadWriteLock接口] --> RWLImpl[ReentrantReadWriteLock] RWLImpl --> RLock RWLImpl --> WLock Cond[Condition接口] --> CondObj[ConditionObject] %% AQS层 AQS[AQS] --> Sync[Sync] AQS --> RWSync[ReadWriteSync] Sync --> FSync[FairSync] Sync --> NFSync[NonfairSync] %% 组合关系 RL -.-> Sync RWLImpl -.-> RWSync RLock -.-> RWSync WLock -.-> RWSync Sync -.-> CondObj RWSync -.-> CondObj style Lock fill:#f9f style RWL fill:#f9f style Cond fill:#f9f style AQS fill:#ccf style RL fill:#cfc style RWLImpl fill:#cfc style RLock fill:#cfc style WLock fill:#cfc

详细版继承结构类图UML:

classDiagram %% ========== 核心接口和抽象类 ========== class Lock { <> +lock() void +lockInterruptibly() void +tryLock() boolean +tryLock(long, TimeUnit) boolean +unlock() void +newCondition() Condition } class ReadWriteLock { <> +readLock() Lock +writeLock() Lock } class Condition { <> +await() void +await(long, TimeUnit) boolean +awaitNanos(long) long +awaitUninterruptibly() void +signal() void +signalAll() void } class AbstractQueuedSynchronizer { <> #state : int #head : Node #tail : Node #getState() int #setState(int) void #compareAndSetState(int, int) boolean #tryAcquire(int) boolean #tryRelease(int) boolean #tryAcquireShared(int) int #tryReleaseShared(int) boolean #isHeldExclusively() boolean #acquire(int) void #acquireInterruptibly(int) void #release(int) boolean #acquireShared(int) void #releaseShared(int) boolean } class AbstractOwnableSynchronizer { <> #exclusiveOwnerThread : Thread #getExclusiveOwnerThread() Thread #setExclusiveOwnerThread(Thread) void } %% ========== ReentrantLock 相关 ========== class ReentrantLock { -sync : Sync +ReentrantLock() +ReentrantLock(boolean) +lock() void +lockInterruptibly() void +tryLock() boolean +tryLock(long, TimeUnit) boolean +unlock() void +isFair() boolean +isLocked() boolean +isHeldByCurrentThread() boolean +getHoldCount() int +getQueueLength() int +hasQueuedThreads() boolean +newCondition() Condition } class Sync { <> +lock() void +nonfairTryAcquire(int) boolean +tryRelease(int) boolean +isHeldExclusively() boolean +newCondition() ConditionObject } class FairSync { +lock() void #tryAcquire(int) boolean } class NonfairSync { +lock() void #tryAcquire(int) boolean } %% ========== ReentrantReadWriteLock 相关 ========== class ReentrantReadWriteLock { -sync : Sync -readerLock : ReadLock -writerLock : WriteLock +ReentrantReadWriteLock() +ReentrantReadWriteLock(boolean) +readLock() Lock +writeLock() Lock +isFair() boolean +getReadLockCount() int +isWriteLocked() boolean +isWriteLockedByCurrentThread() boolean +getWriteHoldCount() int +getReadHoldCount() int } class ReadLock { -sync : Sync +lock() void +lockInterruptibly() void +tryLock() boolean +tryLock(long, TimeUnit) boolean +unlock() void +newCondition() Condition } class WriteLock { -sync : Sync +lock() void +lockInterruptibly() void +tryLock() boolean +tryLock(long, TimeUnit) boolean +unlock() void +newCondition() Condition +isHeldByCurrentThread() boolean +getHoldCount() int } class Sync { <> +tryAcquire(int) boolean +tryRelease(int) boolean +tryAcquireShared(int) int +tryReleaseShared(int) boolean +isHeldExclusively() boolean +newCondition() ConditionObject } class FairSync { #writerShouldBlock() boolean #readerShouldBlock() boolean } class NonfairSync { #writerShouldBlock() boolean #readerShouldBlock() boolean } %% ========== StampedLock 相关 ========== class StampedLock { +StampedLock() +readLock() long +tryReadLock() long +tryReadLock(long, TimeUnit) long +readLockInterruptibly() long +writeLock() long +tryWriteLock() long +tryWriteLock(long, TimeUnit) long +writeLockInterruptibly() long +tryOptimisticRead() long +validate(long) boolean +unlock(long) void +unlockRead(long) void +unlockWrite(long) void +tryConvertToWriteLock(long) long +tryConvertToReadLock(long) long +tryConvertToOptimisticRead(long) long +isReadLocked() boolean +isWriteLocked() boolean +getReadLockCount() int } %% ========== AQS 内部类 ========== class Node { <> +SHARED : Node +EXCLUSIVE : Node +CANCELLED : int +SIGNAL : int +CONDITION : int +PROPAGATE : int +waitStatus : int +prev : Node +next : Node +thread : Thread +nextWaiter : Node +isShared() boolean +predecessor() Node } class ConditionObject { +firstWaiter : Node +lastWaiter : Node +await() void +await(long, TimeUnit) boolean +awaitNanos(long) long +awaitUninterruptibly() void +signal() void +signalAll() void +hasWaiters(ConditionObject) boolean +getWaitQueueLength(ConditionObject) int +getWaitingThreads(ConditionObject) Collection~Thread~ } %% ========== 其他相关类 ========== class LockSupport { <> +park() void +park(Object) void +parkNanos(long) void +parkUntil(long) void +unpark(Thread) void +getBlocker(Thread) Object } class TimeUnit { <> +NANOSECONDS +MICROSECONDS +MILLISECONDS +SECONDS +MINUTES +HOURS +DAYS +toNanos(long) long +toMicros(long) long +toMillis(long) long +toSeconds(long) long +toMinutes(long) long +toHours(long) long +toDays(long) long } %% ========== 继承关系 ========== Lock <|.. ReentrantLock Lock <|.. ReadLock Lock <|.. WriteLock Condition <|.. ConditionObject ReadWriteLock <|.. ReentrantReadWriteLock AbstractOwnableSynchronizer <|-- AbstractQueuedSynchronizer AbstractQueuedSynchronizer <|-- ReentrantLock.Sync AbstractQueuedSynchronizer <|-- ReentrantReadWriteLock.Sync ReentrantLock.Sync <|-- ReentrantLock.FairSync ReentrantLock.Sync <|-- ReentrantLock.NonfairSync ReentrantReadWriteLock.Sync <|-- ReentrantReadWriteLock.FairSync ReentrantReadWriteLock.Sync <|-- ReentrantReadWriteLock.NonfairSync %% ========== 关联关系 ========== ReentrantLock *-- "1" Sync : contains ReentrantReadWriteLock *-- "1" Sync : contains ReentrantReadWriteLock *-- "1" ReadLock : contains ReentrantReadWriteLock *-- "1" WriteLock : contains ReadLock *-- "1" Sync : uses WriteLock *-- "1" Sync : uses Sync *-- "1" ConditionObject : creates AbstractQueuedSynchronizer *-- "0..*" Node : manages ConditionObject *-- "0..*" Node : manages %% ========== 依赖关系 ========== ReentrantLock ..> TimeUnit : uses in tryLock() ReadLock ..> TimeUnit : uses in tryLock() WriteLock ..> TimeUnit : uses in tryLock() ConditionObject ..> TimeUnit : uses in await() LockSupport ..> Thread : manages AbstractQueuedSynchronizer ..> LockSupport : uses ConditionObject ..> LockSupport : uses

使用方式

ReentrantLock 使用示例

java 复制代码
package concurrent;

import java.util.concurrent.*;
import java.util.concurrent.locks.*;

public class ReentrantLockDemo {
    private final ReentrantLock lock = new ReentrantLock();
    private int counter = 0;

    // 1. 基本 lock() 和 unlock()
    public void basicLock() {
        lock.lock();
        try {
            counter++;
            System.out.println(Thread.currentThread().getName() +
                    " [basicLock] 计数器: " + counter);
            Thread.sleep(100); // 模拟工作
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            lock.unlock();
        }
    }

    /** 持锁一段时间,用于配合 lockInterruptibly 演示 */
    public void holdLock(long millis) {
        lock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + " 持有锁 " + millis + "ms");
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            lock.unlock();
            System.out.println(Thread.currentThread().getName() + " 释放锁");
        }
    }

    // 2. tryLock(timeout) - 超时尝试获取锁
    public void tryLockWithTimeout() {
        try {
            if (lock.tryLock(500, TimeUnit.MILLISECONDS)) {
                try {
                    System.out.println(Thread.currentThread().getName() +
                            " [tryLockTimeout] 在500ms内获取成功");
                    Thread.sleep(200); // 模拟工作
                } finally {
                    lock.unlock();
                }
            } else {
                System.out.println(Thread.currentThread().getName() +
                        " [tryLockTimeout] 获取超时");
            }
        } catch (InterruptedException e) {
            System.out.println(Thread.currentThread().getName() +
                    " [tryLockTimeout] 被中断");
            Thread.currentThread().interrupt();
        }
    }

    // 3. lockInterruptibly() - 可中断锁(在等待锁的过程中可被 interrupt 并抛出 InterruptedException)
    public void lockInterruptiblyExample() throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + " 尝试 lockInterruptibly(),若锁被占用将阻塞等待...");
        lock.lockInterruptibly(); // 阻塞等待期间若被 interrupt,会抛出 InterruptedException
        try {
            System.out.println(Thread.currentThread().getName() + " 获取锁成功,执行业务");
            Thread.sleep(500);
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
                System.out.println(Thread.currentThread().getName() + " 释放锁");
            }
        }
    }

    // 运行 ReentrantLock 所有示例
    public static void main(String[] args) throws Exception {
        System.out.println("\n========== ReentrantLock 示例开始 ==========");

        ReentrantLockDemo reentrantDemo = new ReentrantLockDemo();
        // 1. 基本 lock() 示例
        System.out.println("\n1. 基本 lock() 示例:");
        Thread t1 = new Thread(() -> reentrantDemo.basicLock(), "Thread-1");
        Thread t2 = new Thread(() -> reentrantDemo.basicLock(), "Thread-2");
        t1.start();
        t2.start();
        t1.join();
        t2.join();

        // 2. tryLock(timeout) 示例
        System.out.println("\n2. tryLock(timeout) 示例:");
        Thread t5 = new Thread(() -> reentrantDemo.tryLockWithTimeout(), "Thread-5");
        Thread t6 = new Thread(() -> reentrantDemo.tryLockWithTimeout(), "Thread-6");
        t5.start();
        t6.start();
        t5.join();
        t6.join();

        // 3. lockInterruptibly() 示例:先让一个线程持锁,另一个线程在 lockInterruptibly() 上阻塞,再中断阻塞线程
        System.out.println("\n3. lockInterruptibly() 示例(在等待锁时被中断):");
        Thread holder = new Thread(() -> reentrantDemo.holdLock(5000), "Holder");
        Thread interruptible = new Thread(() -> {
            try {
                reentrantDemo.lockInterruptiblyExample();
                System.out.println("Interruptible-Thread 正常结束");
            } catch (InterruptedException e) {
                System.out.println("Interruptible-Thread 在等待锁时被中断,抛出 InterruptedException");
                Thread.currentThread().interrupt();
            }
        }, "Interruptible-Thread");

        holder.start();
        Thread.sleep(100); // 确保 Holder 先拿到锁
        interruptible.start();
        Thread.sleep(800); // 此时 Interruptible 正在 lockInterruptibly() 上阻塞
        interruptible.interrupt(); // 中断正在等待锁的线程
        interruptible.join();
        holder.join();

        System.out.println("\n========== ReentrantLock 示例结束 ==========");
    }
}

代码运行结果:

text 复制代码
========== ReentrantLock 示例开始 ==========

1. 基本 lock() 示例:
Thread-1 [basicLock] 计数器: 1
Thread-2 [basicLock] 计数器: 2

2. tryLock(timeout) 示例:
Thread-5 [tryLockTimeout] 在500ms内获取成功
Thread-6 [tryLockTimeout] 在500ms内获取成功

3. lockInterruptibly() 示例(在等待锁时被中断):
Holder 持有锁 5000ms
Interruptible-Thread 尝试 lockInterruptibly(),若锁被占用将阻塞等待...
Interruptible-Thread 在等待锁时被中断,抛出 InterruptedException
Holder 释放锁

========== ReentrantLock 示例结束 ==========

ReentrantLock 使用示例

java 复制代码
package concurrent;

import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
 * ReentrantReadWriteLock 使用示例:
 * - 读锁(readLock):共享,多线程可同时持有,与写锁互斥
 * - 写锁(writeLock):独占,同一时刻仅一个线程可持有,与读锁、写锁均互斥
 */
public class ReentrantReadWriteLockDemo {

    private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
    private final ReentrantReadWriteLock.ReadLock readLock = rwLock.readLock();
    private final ReentrantReadWriteLock.WriteLock writeLock = rwLock.writeLock();
    private String data = "initial";

    // 1. 读锁:多个线程可同时读
    public void readWithReadLock() {
        System.out.println(Thread.currentThread().getName() + " 尝试获取读锁");
        readLock.lock();  // 若写锁被占用,会在此阻塞
        try {
            System.out.println(Thread.currentThread().getName() + " 获取到读锁(写锁已释放后才会执行到这里)");
            System.out.println(Thread.currentThread().getName() + " [读锁] 读取: " + data);
            Thread.sleep(200);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            readLock.unlock();
        }
    }

    // 2. 写锁:独占,同一时刻只有一个线程可写
    public void writeWithWriteLock(String newData) {
        writeLock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + " [写锁] 写入: " + newData);
            data = newData;
            Thread.sleep(300);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            writeLock.unlock();
        }
    }

    // 3. 持写锁一段时间,用于演示读/写互斥
    public void holdWriteLock(long millis) {
        writeLock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + " 持有写锁 " + millis + "ms(此时读锁会阻塞)");
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            // 先打印再 unlock,保证控制台顺序能体现:先释放写锁,后读者才拿到读锁
            System.out.println(Thread.currentThread().getName() + " 释放写锁");
            writeLock.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ReentrantReadWriteLockDemo demo = new ReentrantReadWriteLockDemo();

        System.out.println("========== 1. 读锁共享:多个线程同时读 ==========");
        Thread r1 = new Thread(() -> demo.readWithReadLock(), "Reader-1");
        Thread r2 = new Thread(() -> demo.readWithReadLock(), "Reader-2");
        Thread r3 = new Thread(() -> demo.readWithReadLock(), "Reader-3");
        r1.start();
        r2.start();
        r3.start();
        r1.join();
        r2.join();
        r3.join();

        System.out.println("\n========== 2. 写锁独占:同一时刻只有一个写 ==========");
        Thread w1 = new Thread(() -> demo.writeWithWriteLock("A"), "Writer-1");
        Thread w2 = new Thread(() -> demo.writeWithWriteLock("B"), "Writer-2");
        w1.start();
        w2.start();
        w1.join();
        w2.join();

        System.out.println("\n========== 3. 读与写互斥:写锁持有时,读锁阻塞 ==========");
        Thread holder = new Thread(() -> demo.holdWriteLock(2000), "Writer-Holder");
        Thread reader = new Thread(() -> demo.readWithReadLock(), "Reader-Blocked");
        holder.start();
        Thread.sleep(100);
        reader.start();
        holder.join();
        reader.join();

        System.out.println("\n========== ReentrantReadWriteLock 示例结束 ==========");
    }
}

代码运行结果:

text 复制代码
========== 1. 读锁共享:多个线程同时读 ==========
Reader-1 尝试获取读锁
Reader-2 尝试获取读锁
Reader-3 尝试获取读锁
Reader-1 获取到读锁(写锁已释放后才会执行到这里)
Reader-2 获取到读锁(写锁已释放后才会执行到这里)
Reader-3 获取到读锁(写锁已释放后才会执行到这里)
Reader-1 [读锁] 读取: initial
Reader-3 [读锁] 读取: initial
Reader-2 [读锁] 读取: initial

========== 2. 写锁独占:同一时刻只有一个写 ==========
Writer-1 [写锁] 写入: A
Writer-2 [写锁] 写入: B

========== 3. 读与写互斥:写锁持有时,读锁阻塞 ==========
Writer-Holder 持有写锁 2000ms(此时读锁会阻塞)
Reader-Blocked 尝试获取读锁
Writer-Holder 释放写锁
Reader-Blocked 获取到读锁(写锁已释放后才会执行到这里)
Reader-Blocked [读锁] 读取: B

========== ReentrantReadWriteLock 示例结束 ==========

Lock 原理

Java lock机制使用AQS来管理锁的状态,进而管理同步锁的获取和释放。

使用AQS管理锁状态

AQS (AbstractQueuedSynchronizer) 是一个抽象接口,核心代码如下:

java 复制代码
// AQS 简化实现原理
public abstract class AbstractQueuedSynchronizer {
    
    // 核心字段1: 同步状态(32位int)
    private volatile int state;
    
    // 核心字段2: CLH队列(双向链表)
    private transient volatile Node head;  // 队列头
    private transient volatile Node tail;  // 队列尾
    
    // 队列节点
    static final class Node {
        volatile Node prev;      // 前驱节点
        volatile Node next;      // 后继节点
        volatile Thread thread;  // 等待的线程
        volatile int waitStatus; // 等待状态
        Node nextWaiter;        // 条件队列使用
    }
    
    // 核心方法:CAS操作
    protected final boolean compareAndSetState(int expect, int update) {
        return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
    }
}

ReentrantLock 使用 AQS 的 state 字段表示锁状态,类内部存在一个Sync内部类:

java 复制代码
// ReentrantLock 使用 AQS 的 state 字段表示锁状态
public class ReentrantLock {
    abstract static class Sync extends AbstractQueuedSynchronizer {
        // state 含义:
        // 0: 无锁状态
        // 1: 有线程持有锁(非重入)
        // N: 同一个线程重入了 N-1 次
    }
}

基于lock获取同步锁时,会经历以下流程:

graph TD A[线程尝试获取锁] --> B{是否持有锁?} B -->|是| C[重入计数+1] B -->|否| D{state是否为0?} D -->|是| E{公平锁?} E -->|是| F{有前驱节点?} F -->|无| G[CAS获取锁] F -->|有| H[入队等待] E -->|否| I[直接CAS尝试] I -->|成功| J[获取成功] I -->|失败| H D -->|否| H G --> K[获取成功] H --> L[进入CLH队列] L --> M[自旋或挂起] M --> N[被唤醒后尝试]

这里内部类Sync实现主要有公平锁和非公平锁两种实现,本文不展开深入,可看下篇文章。另外,这里涉及到的CLH 队列是一种自旋锁的等待队列实现,全称为 Craig, Landin, and Hagersten queue,是 AQS(AbstractQueuedSynchronizer)中实现线程排队等待的核心数据结构。

读写锁获取的实现

读写锁这里用到了state字段做了些状态设计:

java 复制代码
static class Sync extends AbstractQueuedSynchronizer {
    // 使用 state 的高16位表示读锁数量,低16位表示写锁重入次数
    // state = (读锁数量 << 16) | 写锁重入次数
    
    static final int SHARED_SHIFT   = 16;
    static final int SHARED_UNIT    = (1 << SHARED_SHIFT);  // 读锁单位: 65536
    static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;  // 最大计数: 65535
    static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;  // 写锁掩码: 0xFFFF
    
    // 获取读锁数量
    static int sharedCount(int c)    { return c >>> SHARED_SHIFT; }
    
    // 获取写锁重入次数
    static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
}

写锁获取的核心方法如下:

java 复制代码
// WriteLock 的 tryAcquire 方法
protected final boolean tryAcquire(int acquires) {
    Thread current = Thread.currentThread();
    int c = getState();
    int w = exclusiveCount(c);  // 获取写锁数量
    
    if (c != 0) {  // 有锁被持有
        // 情况1: 有读锁 (w == 0 但 c != 0)
        // 情况2: 有写锁但不是当前线程持有 (w != 0 && 持有者 != current)
        if (w == 0 || current != getExclusiveOwnerThread())
            return false;  // 获取失败
        
        // 情况3: 当前线程持有写锁(重入)
        if (w + exclusiveCount(acquires) > MAX_COUNT)
            throw new Error("Maximum lock count exceeded");
        setState(c + acquires);
        return true;
    }
    
    // c == 0 无锁状态
    if (writerShouldBlock() ||  // 公平性检查
        !compareAndSetState(c, c + acquires))
        return false;
    
    setExclusiveOwnerThread(current);
    return true;
}

读锁获取核心方法如下:

java 复制代码
// ReadLock 的 tryAcquireShared 方法
protected final int tryAcquireShared(int unused) {
    Thread current = Thread.currentThread();
    int c = getState();
    
    // 如果有写锁,并且不是当前线程持有的
    if (exclusiveCount(c) != 0 &&
        getExclusiveOwnerThread() != current)
        return -1;  // 获取失败
    
    int r = sharedCount(c);  // 当前读锁数量
    
    // 检查是否应该阻塞(公平性检查)
    if (!readerShouldBlock() &&
        r < MAX_COUNT &&
        compareAndSetState(c, c + SHARED_UNIT)) {
        
        // 第一个读锁
        if (r == 0) {
            firstReader = current;
            firstReaderHoldCount = 1;
        }
        // 当前线程是第一个读锁持有者
        else if (firstReader == current) {
            firstReaderHoldCount++;
        }
        // 其他线程持有读锁
        else {
            HoldCounter rh = cachedHoldCounter;
            if (rh == null || rh.tid != current.getId())
                cachedHoldCounter = rh = readHolds.get();
            else if (rh.count == 0)
                readHolds.set(rh);
            rh.count++;
        }
        return 1;  // 获取成功
    }
    
    // CAS失败或应该阻塞,进入完整获取流程
    return fullTryAcquireShared(current);
}
相关推荐
加洛斯2 小时前
RabbitMQ入门篇(1):初识MQ
java·后端
苏三说技术2 小时前
Nacos 和 Apollo,哪个更好?
后端
程序员清风3 小时前
2026年必学:Vibe Coding几个实用技巧,老手都在偷偷用!
java·后端·面试
忙碌5443 小时前
Spring Boot应用Docker化部署全攻略:从入门到生产环境实践
spring boot·后端·docker
Cache技术分享3 小时前
333. Java Stream API - 按年份找出合作最多的作者对:避免 Optional.orElseThrow() 的风险
前端·后端
Mintopia3 小时前
又快又好的系统是怎么做出来的
后端
数字之心AIEvangelist3 小时前
OpenClaw 会话机制与记忆系统深度剖析
后端
树獭叔叔3 小时前
04-残差连接与Pre-LN:让大模型的深度网络成为可能
后端·aigc·openai
Assby3 小时前
深入理解Java:为什么String类要用final修饰?
后端·面试