synchronized 是 Java 关键字,简单易用、自动释放锁;Lock 是 JUC 包下的接口(常用实现 ReentrantLock),功能更灵活,但需要手动释放锁,稍复杂。

特性 synchronized Lock(以 ReentrantLock 为例)
本质 Java 关键字,JVM 层面实现 接口,Java 代码层面实现(API 层面)
锁释放 自动释放(出代码块 / 方法 / 抛异常时) 必须手动释放(unlock()),建议放 finally
锁获取 只有一种方式:阻塞等待 支持多种方式:1. 阻塞等待(lock())2. 尝试获取(tryLock())3. 超时获取(tryLock(timeout, unit)
锁状态 无法判断是否获取到锁 可通过 isLocked()/tryLock() 判断
公平锁 非公平锁(默认),无法指定公平性 支持公平 / 非公平锁(构造方法指定 new ReentrantLock(true)
可中断 不可中断(获取锁时只能死等) 支持可中断(lockInterruptibly()
条件变量(Condition) 只有一个条件队列(wait/notify) 支持多个条件队列(newCondition()),精准唤醒线程
性能 JDK1.6 后优化(偏向锁 / 轻量级锁),低竞争下和 Lock 差不多 高竞争场景下性能更优,灵活度更高
  1. synchronized 用法(简单,自动释放)
public class SyncDemo {
    // 共享资源
    private int count = 0;

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

    // synchronized 代码块(更灵活)
    public void decrement() {
        synchronized (this) {
            count--;
        }
    }

    public int getCount() {
        return count;
    }
}

优点:不用管释放,代码简洁,新手不易出错。
缺点:如果获取锁的线程卡住,其他线程只能一直等,没有退路。

  1. Lock 用法(灵活,手动释放)
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LockDemo {
    private int count = 0;
    // 创建可重入锁(公平锁:new ReentrantLock(true))
    private final Lock lock = new ReentrantLock();

    public void increment() {
        // 加锁
        lock.lock();
        try {
            count++; // 核心逻辑
        } finally {
            // 必须在 finally 中释放,避免异常导致锁泄漏
            lock.unlock();
        }
    }

    // 尝试获取锁(不会死等)
    public boolean tryDecrement() {
        // 尝试获取锁,1秒内获取不到就放弃
        if (lock.tryLock(1, java.util.concurrent.TimeUnit.SECONDS)) {
            try {
                count--;
                return true;
            } finally {
                lock.unlock();
            }
        }
        return false; // 获取锁失败
    }

    public int getCount() {
        return count;
    }
}

两者都是可重入锁:同一个线程可以多次获取同一把锁,不会自己锁死自己。

// synchronized 可重入
public synchronized void methodA() {
    methodB(); // 同一个线程调用,不会死锁
}
public synchronized void methodB() {}

// Lock 可重入
public void methodC() {
    lock.lock();
    try {
        methodD();
    } finally {
        lock.unlock();
    }
}
public void methodD() {
    lock.lock();
    try { /* 逻辑 */ } finally { lock.unlock(); }
}

总结

  • synchronized:关键字、自动释放、简单易用,适合大部分基础同步场景。
  • Lock:接口、手动释放(必写 finally)、功能丰富(尝试获取 / 超时 / 公平锁),适合复杂并发场景。
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐