java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java并发锁机制

Java并发锁机制知识总结(最新整理)

作者:秋风不识晚间路

Java 的锁机制是并发编程的核心,用于解决多线程共享资源竞争问题,保证数据一致性和线程安全,这篇文章给大家介绍Java并发锁机制知识总结,感兴趣的朋友跟随小编一起看看吧

并发锁机制知识总结

Java 的锁机制是并发编程的核心,用于解决多线程共享资源竞争问题,保证数据一致性和线程安全。Java 提供了内置锁(synchronized)显式锁(Lock 接口) 等多种锁实现,同时衍生出偏向锁、轻量级锁、重量级锁等优化机制,以及可重入锁、公平锁、读写锁等功能分类。

一、锁的核心作用

二、Java 锁的分类

(一)按实现方式:内置锁 vs 显式锁

1. 内置锁:synchronized(JVM 层面实现)

synchronized 是 Java 原生的隐式锁,基于 对象监视器(Monitor) 实现,无需手动释放,简单易用、线程安全。

(1)使用场景

(2)示例代码

public class SynchronizedDemo {
    // 1. 实例方法锁(锁:this)
    public synchronized void method1() {
        // 共享资源操作
    }
    // 2. 静态方法锁(锁:SynchronizedDemo.class)
    public static synchronized void method2() {
        // 共享资源操作
    }
    // 3. 代码块锁(锁:自定义对象)
    private final Object lock = new Object();
    public void method3() {
        synchronized (lock) {
            // 共享资源操作
        }
    }
}

(3)核心特性

(4)JVM 优化:锁升级(无锁 → 偏向锁 → 轻量级锁 → 重量级锁)

为了平衡性能和并发安全,JVM 对 synchronized 进行了锁升级优化(从低开销到高开销逐步过渡):

锁升级是不可逆的(一旦升级为重量级锁,不会降级)。

2. 显式锁:Lock 接口(Java 代码层面实现)

java.util.concurrent.locks.Lock 是 JDK 1.5 引入的显式锁,提供比 synchronized 更灵活的功能(如可中断、超时获取、公平锁等),但需手动释放锁(否则会导致死锁)。

(1)核心方法

方法作用
lock()获取锁(阻塞,不可中断)
lockInterruptibly()获取锁(可被中断,抛出 InterruptedException
tryLock()尝试获取锁(非阻塞,成功返回 true,失败返回 false
tryLock(long time, TimeUnit unit)超时获取锁(超时未获取则返回 false
unlock()释放锁(必须在 finally 中调用)
newCondition()创建条件变量(实现线程等待 / 唤醒)

(2)常用实现类

(3)示例代码(ReentrantLock)

import java.util.concurrent.locks.ReentrantLock;
public class LockDemo {
    // 创建非公平锁(默认),若要公平锁:new ReentrantLock(true)
    private final ReentrantLock lock = new ReentrantLock();
    public void method() {
        // 1. 获取锁(必须手动获取)
        lock.lock();
        try {
            // 共享资源操作
        } finally {
            // 2. 释放锁(必须在 finally 中释放,避免锁泄漏)
            lock.unlock();
        }
    }
    // 可中断获取锁示例
    public void interruptibleMethod() throws InterruptedException {
        lock.lockInterruptibly(); // 线程可被中断
        try {
            // 共享资源操作
        } finally {
            lock.unlock();
        }
    }
}

(4)核心特性

(二)按功能特性分类

1. 可重入锁 vs 不可重入锁

2. 公平锁 vs 非公平锁

3. 读写锁(ReentrantReadWriteLock)

针对 “读多写少” 场景优化,分离读锁(共享锁)写锁(排他锁)

import java.util.concurrent.locks.ReentrantReadWriteLock;
public class ReadWriteLockDemo {
    private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();
    private final ReentrantReadWriteLock.ReadLock readLock = rwLock.readLock();
    private final ReentrantReadWriteLock.WriteLock writeLock = rwLock.writeLock();
    private int data;
    // 读操作(共享锁)
    public int readData() {
        readLock.lock();
        try {
            return data;
        } finally {
            readLock.unlock();
        }
    }
    // 写操作(排他锁)
    public void writeData(int value) {
        writeLock.lock();
        try {
            data = value;
        } finally {
            writeLock.unlock();
        }
    }
}

4. 乐观锁 vs 悲观锁

(三)其他特殊锁

1. 自旋锁(SpinLock)

线程获取锁失败时,不立即阻塞,而是循环(自旋)尝试获取锁(避免线程上下文切换开销)。

2. 偏向锁 / 轻量级锁 / 重量级锁(JVM 层面的锁优化)

见前文 synchronized 的锁升级机制,核心是 “按需升级”,平衡性能和并发安全。

3. StampedLock(乐观读锁)

JDK 1.8 引入,性能优于 ReentrantReadWriteLock,支持三种模式:

三、synchronized vs ReentrantLock 对比

特性synchronizedReentrantLock
实现层面JVM 层面(底层是 Monitor)Java 代码层面(AQS 框架)
可重入性支持支持
公平性仅非公平锁公平 / 非公平可选
可中断性不支持支持(lockInterruptibly ())
超时获取不支持支持(tryLock (time))
条件变量仅一个(wait ()/notify ())多个(newCondition ())
锁释放自动释放(退出同步块 / 方法)手动释放(必须在 finally 中 unlock ())
性能JDK 1.6 后优化(锁升级),性能接近 ReentrantLock高(灵活控制)
适用场景简单场景(无需复杂功能)复杂场景(需中断、超时、公平锁等)

四、锁的使用注意事项

总结

Java 锁机制的核心是解决共享资源竞争,提供了从简单到复杂的多种实现:

使用锁时需平衡线程安全性能,避免死锁、锁粒度过大等问题,根据实际场景选择合适的锁类型。
最后祝各位开发者工作顺利,万事如意。

  1. 避免死锁:
    • 手动释放锁(ReentrantLock 必须在 finally 中 unlock ())。
    • 避免嵌套锁(或保证嵌套锁的获取顺序一致)。
    • 避免长时间持有锁(减少锁竞争)。
  2. 选择合适的锁类型:
    • 读多写少:用 ReentrantReadWriteLockStampedLock
    • 简单场景:用 synchronized(无需手动管理锁)。
    • 复杂场景(中断、超时、公平锁):用 ReentrantLock
  3. 减少锁粒度:
    • 避免锁覆盖整个方法(仅对共享资源的操作加锁,如 synchronized 代码块而非方法)。
    • 示例:用 synchronized (lock) 替代 synchronized method()(仅锁定关键代码)。
  4. 避免锁竞争:
    • 无状态对象无需加锁(无共享资源)。
    • 共享资源尽量设计为不可变(如 StringInteger)。
    • 用局部变量替代共享变量(线程私有,无需锁)。

到此这篇关于Java-并发锁机制知识总结的文章就介绍到这了,更多相关Java并发锁机制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文