lock和Synchronized区别
                           
天天向上
发布: 2025-07-12 13:31:39

原创
210 人浏览过

好的,下面我从多个维度,全面详细地讲解 Java 中的 lock(以 ReentrantLock 为代表)和 synchronized 的区别,包含原理、性能、用法和适用场景,并附带官方资料链接。


一、基本概念

方面synchronizedLock(通常指 ReentrantLock
语法Java 关键字,内置语言结构接口和实现类,Java.util.concurrent.locks 包
功能用于同步代码块或方法,保证线程互斥执行提供更灵活的锁机制,支持公平锁、可中断锁等
出现时间Java 1.0 就有Java 5 引入

二、详细区别

比较维度synchronizedReentrantLock
锁类型内置锁(监视器锁,Monitor Lock)显式锁(基于 AQS 实现的可重入独占锁)
灵活性只能锁整个方法或代码块提供更多方法如 lockInterruptibly()tryLock()
可中断性不支持中断等待锁(阻塞不可中断)支持可中断锁请求,调用线程可被中断
公平锁支持不支持公平锁支持公平锁和非公平锁(默认非公平)
锁释放方式JVM 自动释放锁(代码块结束自动释放)需手动调用 unlock() 释放,容易忘记导致死锁
性能JDK 1.6+ 引入偏向锁、轻量级锁优化,性能提升显著性能稳定,复杂场景下有优势
死锁检测JVM 不提供显式死锁检测可用 API 查询是否被持有,可实现死锁检测
条件变量支持通过 wait()/notify()/notifyAll() 实现线程通信通过 Condition 对象实现多条件等待/通知
重入性都是可重入锁都是可重入锁
异常处理锁释放自动,异常抛出不会影响锁释放必须在 finally 中释放锁,否则可能死锁

三、使用示例对比

1. synchronized

public synchronized void syncMethod() {
    // 代码块被锁保护
}

public void syncBlock() {
    synchronized (this) {
        // 代码块被锁保护
    }
}

锁释放自动发生,无需显式代码。


2. ReentrantLock

private final ReentrantLock lock = new ReentrantLock();

public void lockMethod() {
    lock.lock();
    try {
        // 代码块被锁保护
    } finally {
        lock.unlock();  // 必须释放锁
    }
}

四、性能比较

  • 早期(JDK 1.5 之前)synchronized性能较差,ReentrantLock 优势明显
  • JDK 1.6+ 引入偏向锁、轻量级锁,synchronized 性能大幅提升
  • 无锁竞争或低竞争环境,synchronized 更轻量
  • 高竞争、多线程等待场景,ReentrantLock 通过灵活调度可更高效

五、功能区别细节

特性synchronizedReentrantLock
公平锁支持,通过构造函数设置
可中断锁不支持支持 lockInterruptibly()
尝试获取锁支持 tryLock()
多条件等待一个条件(wait/notify多个条件支持 Condition
锁释放安全JVM自动释放程序员必须手动释放
代码简洁性简单,写法少代码多,需写 try-finally

六、适用场景建议

场景类型推荐使用
简单同步synchronized
需要公平锁ReentrantLock(构造参数true)
需要可中断锁ReentrantLock
需要尝试非阻塞锁ReentrantLock.tryLock()
需要多个条件变量ReentrantLock + Condition
代码简洁优先synchronized

七、总结表格

特性synchronizedReentrantLock
出现时间Java 1.0Java 5
锁类型JVM 内置锁显式锁
可重入
可中断
公平锁支持
锁释放自动手动
条件变量wait/notifyCondition
代码简洁简单复杂
性能JDK 1.6+ 低竞争时更优高竞争时更优

八、官方参考链接


更多详细内容请关注其他相关文章!

发表回复 0

Your email address will not be published. Required fields are marked *