Java中synchronized与Lock的对比

        在之前的面试中遇到过这样一个问题,synchronized和lock的对比,只回到了4个区别特性,记录一下。

  synchronizedLock都是Java中用于实现线程同步的机制,但它们在实现方式、功能和性能上有显著差异。以下是两者的详细对比:

1. 基本特性对比

特性 synchronized Lock (ReentrantLock)
实现方式 Java关键字,JVM层面实现 Java类,API层面实现
获取与释放 自动获取和释放锁 需要手动调用lock()和unlock()
锁的类型 非公平锁 可选择公平锁或非公平锁
可中断性 不可中断 可中断(lockInterruptibly())
尝试获取锁 不支持 支持(tryLock())
超时机制 不支持 支持(tryLock(time, unit))
条件变量 只能有一个条件队列 可创建多个Condition对象
性能 JDK6后优化,性能接近 高竞争下性能可能更好

 

2. 详细比较

2.1 使用方式

synchronized:

public synchronized void method() {
    // 同步代码
}

// 或
public void method() {
    synchronized(this) {
        // 同步代码块
    }
}

Lock:

private Lock lock = new ReentrantLock();

public void method() {
    lock.lock();
    try {
        // 同步代码
    } finally {
        lock.unlock();
    }
}

2.2 高级功能

Lock提供而synchronized不具备的功能:

  • 尝试非阻塞获取锁tryLock()

  • 可中断的获取锁lockInterruptibly()

  • 超时获取锁tryLock(long time, TimeUnit unit)

  • 公平锁new ReentrantLock(true)

  • 多个条件变量newCondition()

2.3 性能考虑

  • 在低竞争情况下,synchronized性能与Lock相当

  • 在高竞争情况下,Lock通常表现更好

  • synchronized有优化空间(锁升级:偏向锁→轻量级锁→重量级锁)

  • Lock需要手动释放锁,容易忘记导致死锁

  • 内存占用 synchronized通常更节省内存(特别是无竞争时);Lock需要额外对象来维护状态和队列

2.4 扩展性

  • Lock的等待队列实现更适合大量线程竞争

  • synchronized的Monitor在大量线程竞争时可能成为瓶颈

2.5 选择建议

使用synchronized的情况:

  • 简单的同步需求

  • 不需要高级功能

  • 希望代码更简洁

  • 锁的获取和释放在一个方法内完成

使用Lock的情况:

  • 需要高级功能(可中断、超时、尝试获取等)

  • 需要公平锁

  • 需要多个条件变量

  • 锁需要在多个方法间传递和释放

  • 高竞争环境下对性能有更高要求

3. 示例对比

3.1 可中断锁示例

使用Lock:

Lock lock = new ReentrantLock();
try {
    lock.lockInterruptibly();
    // 同步代码
} catch (InterruptedException e) {
    // 处理中断
} finally {
    lock.unlock();
}

synchronized无法实现可中断锁

3.2 尝试获取锁示例

使用Lock:

 if (lock.tryLock()) {
    try {
        // 获取锁成功
    } finally {
        lock.unlock();
    }
} else {
    // 获取锁失败
}

 synchronized无法实现尝试获取锁

4. 总结

synchronized是Java内置的同步机制,使用简单但功能有限;Lock提供了更丰富的功能但需要手动管理。在大多数情况下,synchronized已经足够,只有在需要其不具备的高级功能时,才应考虑使用Lock

你可能感兴趣的:(java基础,java,lock,synchronized)