Java中synchronized和Lock 接口
·
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 差不多 | 高竞争场景下性能更优,灵活度更高 |
- 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;
}
}
优点:不用管释放,代码简洁,新手不易出错。
缺点:如果获取锁的线程卡住,其他线程只能一直等,没有退路。
- 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)、功能丰富(尝试获取 / 超时 / 公平锁),适合复杂并发场景。
更多推荐
所有评论(0)