Synchronized 与 Lock 相比优缺点分别是什么?
Lock
实现提供比使用 synchronized
方法和语句可以获得的更广泛的锁定操作。 它们允许更灵活的结构化,可能具有完全不同的属性,并且可以支持多个相关联的对象Condition 。
虽然 synchronized
方法和语句的范围机制使得使用监视器锁更容易编程,并且有助于避免涉及锁的许多常见编程错误,但是有时您需要以更灵活的方式处理锁。
例如,您获取节点A的锁定,然后获取节点B,然后释放A并获取C,然后释放B并获得D等。
所述的实施方式中Lock接口通过允许获得并在不同的范围释放的锁,并允许获得并以任何顺序释放多个锁使得能够使用这样的技术。
# Lock 接口 VS Synchronized
Java SE 5之后,juc 包中增加了 Lock 接口,在此之前 Java 是靠 Synchronized
关键字来实现锁功能的,二者具有相同的内存同步语义,区别如下:
Synchronized | Lock接口 | |
---|---|---|
加锁、解锁 | 隐式的加锁、解锁 | 显式的加锁、解锁 |
是否异常自动释放锁 | 是 | 不是,必须手动unlock来释放锁 |
是否支持相应中断 | 只能等待锁的释放,不能响应中断 | 等待锁过程中可以用interrupt来中断等待 |
适用场景 | 比如这种场景:先获得A锁,再获取B锁,获取到B锁释放A锁同时获取C锁,获得C锁后释放B锁在获取D锁。这种场景用Synchronized 就不好实现了。 |
Lock 相比于 Synchronized
还有如下特性:
- 尝试非阻塞获取锁
- 能被中断的获取锁
- 超时获取锁
# Lock 锁的常规用法
Lock l = ...;
l.lock();
try {
// access the resource protected by this lock }
finally {
l.unlock();
}
1
2
3
4
5
6
7
2
3
4
5
6
7
# Lock 锁的API
Lock 接口定义了所得获取和释放的基本操作, Lock的API如下:
方法 | 描述 |
---|---|
void lock() | 获得锁 |
void lockInterruptibly() | 获取锁定,除非当前线程是 interrupted 。 |
Condition newCondition() | 返回一个新Condition绑定到该实例Lock实例。 |
boolean tryLock() | 只有在调用时才可以获得锁。 |
boolean tryLock(long time, TimeUnit unit) | 如果在给定的等待时间内是空闲的,并且当前的线程尚未得到 interrupted,则获取该锁 |
void unlock() | 释放锁。 |
编辑 (opens new window)
上次更新: 2022/05/19, 21:26:01