synchronized是关键字,自动管理锁,使用简单但功能有限;Lock是接口,需手动加锁解锁,支持公平锁、可中断、超时获取等高级功能,灵活性高但需注意异常处理与释放。

在Java中,synchronized 和 Lock 都用于实现线程同步,保证多线程环境下数据的一致性,但它们在使用方式、功能和灵活性上有明显区别。
1. 语法层面的差异
synchronized 是Java语言的关键字,JVM层面支持,使用简单。可以修饰方法或代码块,进入同步区域时自动获取锁,退出时自动释放。
示例:public synchronized void method() {
// 同步方法
}
synchronized(this) {
// 同步代码块
}
Lock 是一个接口(如 ReentrantLock),需要手动创建实例,并显式调用 lock() 和 unlock() 方法控制锁的获取与释放。
示例:Lock lock = new ReentrantLock();
lock.lock();
try {
// 临界区
} finally {
lock.unlock(); // 必须在finally中释放
}
2. 锁的获取与释放控制
synchronized 的锁是自动管理的,线程退出同步代码块或方法后自动释放,即使发生异常也不会导致死锁。
立即学习“Java免费学习笔记(深入)”;
Lock 必须手动释放,如果不调用 unlock(),可能导致其他线程永久等待,造成死锁。因此通常将 unlock() 放在 finally 块中确保执行。
Lock 提供了更灵活的控制方式,比如尝试获取锁(tryLock)、带超时获取锁(tryLock(long, TimeUnit))、可中断地获取锁(lockInterruptibly)等。
- tryLock():立即返回是否获取成功,适合避免阻塞
- tryLock(5, TimeUnit.SECONDS):在指定时间内尝试获取锁
- lockInterruptibly():允许在等待锁的过程中响应中断
3. 公平性支持
synchronized 不支持公平锁,多个线程竞争时无法保证先到先得。
ReentrantLock 可以通过构造函数选择是否使用公平锁:
Lock lock = new ReentrantLock(true); // 公平锁
公平锁能减少线程饥饿问题,但性能较低,因为需要维护等待队列。
4. 性能与适用场景
早期版本中 synchronized 性能较差,但自从JDK 1.6引入偏向锁、轻量级锁等优化后,性能已大幅提升,在大多数场景下与 Lock 差别不大。
如果只是简单的互斥操作,优先使用 synchronized,代码更简洁、安全。
如果需要尝试非阻塞获取锁、超时获取、可中断、条件等待(Condition)等高级功能,则使用 Lock 更合适。
基本上就这些。synchronized 简单可靠,适合大部分同步需求;Lock 功能强大,适合复杂控制场景,但使用要更小心。不复杂但容易忽略的是:手动释放锁和异常处理。










