专注于 JetBrains IDEA 全家桶,永久激活,教程
持续更新 PyCharm,IDEA,WebStorm,PhpStorm,DataGrip,RubyMine,CLion,AppCode 永久激活教程

Java并发锁全解:synchronized、ReentrantLock、AQS底层原理与实战选型指南

在Java 并发编程的世界里,锁就像一个守门员,决定着谁能进、谁得等。如果你还在被 synchronized 搞得头晕,或者对 ReentrantLock、AQS 一知半解,今天就让我们用最通俗易懂的方式,把 Java 锁的前世今生讲个明白!

1. synchronized:并发编程的老伙计

synchronized 关键字是 Java 并发控制的“祖师爷”,它的特点是:
✅简单易用:直接加在方法或代码块上,开发者几乎不用操心底层实现。
✅自动释放:线程执行完 synchronized 代码块后,锁会自动释放,避免死锁。
✅可重入:支持同一个线程多次获取同一把锁,不会发生死锁。

用法示例

public class SynchronizedExample {
    private int count=0;

    public synchronized void increment() { // 修饰方法
        count++;
    }

    public void syncBlock() {
        synchronized (this) { // 修饰代码块
            count++;
        }
    }
}

synchronized 的缺点

  • • 性能较低:它是 JVM 层面的重量级锁,在 Java 早期版本中,线程进入 synchronized 会导致 CPU 上下文切换,影响效率。
  • • 不能尝试获取:如果一个线程获取不到锁,只能傻等,不能像 Lock 那样超时退出。

优化升级:JDK 1.6 之后
JVM针对 synchronized 进行了优化,引入偏向锁、轻量级锁、自旋锁等技术,提升了性能。


2. ReentrantLock:synchronized 的升级版

synchronized 虽然简单,但在高并发场景下显得力不从心。这时,JDK 5 引入了 ReentrantLock,它是 synchronized 的可替代方案,性能更强大。

核心特性

✅可中断:支持 lockInterruptibly(),可以响应中断,避免线程永久阻塞。
✅支持超时:tryLock(timeout, unit) 允许线程等待一段时间,如果超时,则放弃获取锁。
✅公平锁 / 非公平锁:可以选择公平模式(FIFO)或非公平模式(默认,性能更好)。

使用示例

import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockExample {
    private final ReentrantLock lock=new ReentrantLock();

    public void safeMethod() {
        lock.lock(); // 获取锁
        try {
            // 临界区代码
            System.out.println("线程 " + Thread.currentThread().getName() + " 正在执行");
        } finally {
            lock.unlock(); // 释放锁
        }
    }
}

⚠️注意:lock()unlock() 必须配对使用,否则可能导致死锁!

3. AQS(AbstractQueuedSynchronizer):并发锁的终极基石

AQS是 JDK 并发包(java.util.concurrent)的核心,ReentrantLockSemaphoreCountDownLatch 都是基于 AQS 实现的。

AQS 的工作原理

1、 1.CLH队列:AQS采用CLH(Craig,Landin,andHagersten)锁队列来管理等待的线程;
2、 2.独占锁/共享锁:;
3、 •独占锁(ReentrantLock):同一时刻只有一个线程能获取锁;

• 共享锁(ReadWriteLock):允许多个线程同时读取,但写时必须独占。

自定义锁(基于 AQS)

如果你想实现自己的锁,可以继承 AQS 并重写 tryAcquire()tryRelease() 方法:

import java.util.concurrent.locks.AbstractQueuedSynchronizer;

public class CustomLock {
    private static class Sync extends AbstractQueuedSynchronizer {
        @Override
        protected boolean tryAcquire(int arg) {
            if (compareAndSetState(0, 1)) { // CAS 修改 state
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

        @Override
        protected boolean tryRelease(int arg) {
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }
    }

    private final Sync sync = new Sync();

    public void lock() {
        sync.acquire(1);
    }

    public void unlock() {
        sync.release(1);
    }
}

这样,你就实现了一个最简单的可重入锁!

4. 各种锁的比较

锁类型 特点 适用场景
synchronized JVM 层面实现,自动释放锁,低效但简单 适用于简单同步
ReentrantLock 支持超时、公平锁、可中断 适用于高并发场景
ReadWriteLock 读写分离,多个线程可同时读取 适用于读多写少的情况
StampedLock 乐观读锁,提高读性能 适用于写少读多场景
Semaphore 控制并发线程数 限流、资源控制
CountDownLatch 线程计数器,等待多个线程完成任务 任务批量执行
CyclicBarrier 线程屏障,所有线程都到达才执行 任务协同

5. 实战:如何选择合适的锁?

  • • 简单同步 👉 synchronized
  • • 高并发,避免 CPU 切换 👉 ReentrantLock
  • • 读多写少 👉 ReadWriteLock 或 StampedLock
  • • 需要控制并发线程数 👉 Semaphore
  • • 多个任务需要等待完成 👉 CountDownLatch 或 CyclicBarrier

总结

1、 1.synchronized适合简单同步,但性能较低;
2、 2.ReentrantLock提供更灵活的锁机制(可中断、可超时);
3、 3.AQS是ReentrantLockSemaphoreCountDownLatch等的基石;
4、 4.选择合适的锁,能让你的代码更高效!;

你是不是对 Java 并发锁彻底搞明白了?如果你觉得有收获,记得点赞+收藏,以后遇到锁问题,就来翻这篇文章!🚀🚀🚀

未经允许不得转载:搜云库 » Java并发锁全解:synchronized、ReentrantLock、AQS底层原理与实战选型指南

JetBrains 全家桶,激活、破解、教程

提供 JetBrains 全家桶激活码、注册码、破解补丁下载及详细激活教程,支持 IntelliJ IDEA、PyCharm、WebStorm 等工具的永久激活。无论是破解教程,还是最新激活码,均可免费获得,帮助开发者解决常见激活问题,确保轻松破解并快速使用 JetBrains 软件。获取免费的破解补丁和激活码,快速解决激活难题,全面覆盖 2024/2025 版本!

联系我们联系我们