synchronized与lock的区别,使用场景有哪些?

Git高速下载
程序员工具大全

synchronizedLock 是 Java 中两种不同的锁机制,它们在实现方式、功能和适用场景上有显著区别:


核心区别对比

特性synchronizedLock (如 ReentrantLock)
实现层级JVM 层面实现(关键字)JDK 层面实现(接口+实现类)
锁获取/释放自动获取和释放(进入/退出同步块)手动控制(必须显式调用 lock()/unlock()
锁类型非公平锁(默认)可选择公平锁或非公平锁
锁中断❌ 不支持中断等待✅ 支持 lockInterruptibly()
尝试获取锁❌ 不支持✅ 支持 tryLock()(带超时/非阻塞)
条件队列单条件队列(wait()/notify()多条件队列(通过 Condition 实现)
性能Java 6+ 优化后接近 Lock高竞争场景下更优
锁状态❌ 无法查询锁状态✅ 可查询(如 isLocked(), hasQueuedThreads()

使用场景分析

1. 优先使用 synchronized 的场景
  • 简单同步需求
    如单方法内的线程安全控制:

    public synchronized void transfer(Account target, int amount) {
        this.balance -= amount;
        target.balance += amount;
    }
    
  • 资源竞争不激烈
    低并发场景(如内部管理系统),JVM 优化后性能足够。

  • 避免锁泄漏
    自动释放机制防止忘记解锁:

    // synchronized 自动释放
    synchronized (lockObj) {
        // 即使抛出异常也会释放锁
        doSomething();
    }
    
2. 优先使用 Lock 的场景
  • 需要高级锁功能

    Lock lock = new ReentrantLock();
    if (lock.tryLock(1, TimeUnit.SECONDS)) { // 超时获取
        try {
            // 临界区
        } finally {
            lock.unlock();
        }
    } else {
        // 处理超时逻辑
    }
    
  • 公平锁需求
    防止线程饥饿:

    Lock fairLock = new ReentrantLock(true); // 公平锁
    
  • 细粒度条件控制
    生产者-消费者模型:

    Lock lock = new ReentrantLock();
    Condition notEmpty = lock.newCondition();
    Condition notFull = lock.newCondition();
    
    // 生产者
    lock.lock();
    try {
        while (queue.isFull()) notFull.await(); // 只唤醒生产者
        queue.add(item);
        notEmpty.signal();
    } finally { lock.unlock(); }
    
  • 锁中断支持
    应对死锁场景:

    try {
        lock.lockInterruptibly(); // 可响应中断
        // ...
    } catch (InterruptedException e) {
        // 处理中断
    }
    

性能对比

场景synchronizedLock
低竞争✅ 更优(JVM 优化)⚠️ 轻微开销
高竞争⚠️ 竞争激烈时性能下降✅ 更稳定(CAS 优化)
锁升级✅ 无锁→偏向锁→轻量锁→重量锁❌ 直接重量级锁

Java 6+ 中 synchronized 通过锁膨胀优化:
无锁 → 偏向锁(单线程) → 轻量级锁(自旋) → 重量级锁(阻塞)


选择原则

  1. 默认选择 synchronized
    满足需求时优先使用(代码简洁、避免人为错误)
  2. 需要以下特性时选 Lock
    • 超时获取锁
    • 可中断锁
    • 公平锁
    • 多条件变量
    • 锁状态查询
  3. 高并发场景
    根据压测结果选择(Lock 在极高竞争下表现更稳定)

代码示例对比

相同功能的不同实现

使用 synchronized

public class Counter {
    private int count;
    public synchronized void increment() {
        count++;
    }
}

使用 Lock

public class Counter {
    private int count;
    private final Lock lock = new ReentrantLock();
    
    public void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock(); // 必须保证释放
        }
    }
}

⚠️ 关键提示Lock 必须配合 try-finally 确保解锁,否则可能导致死锁!


🐂🐎

维度结论
简洁性synchronized 胜出(自动管理)
功能性Lock 胜出(支持高级特性)
性能低竞争:synchronizedLock
高竞争:Lock 更稳定
最佳实践80% 场景用 synchronized,20% 复杂场景用 Lock

博主建议

  • 优先尝试 synchronized,遇到功能限制时再切换到 Lock
  • 使用 Lock 时务必遵循 lock()tryfinally { unlock() } 模式

程序员面试资料大全|各种技术书籍等资料-1000G
Git高速下载

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值