11显示锁

显示锁

显示锁可以代替 synchronized 吗?

只有当 synchronized 不适用时,如中断,非块结构加锁,是可以代替的一种高级锁。

Lock 和 ReentrantLock

Lock 定义了显示锁的方法属性:

1
2
3
4
5
6
7
8
9
10
public interfece Lock
{
void lock();
void lockInterruptibly() throws InterruptedException;
boolean tryLock();
boolean tryLock(long timeout, TimeUnit unit
throw InterruptedException;
void unlock();
Condition newCondition();
}

ReentrantLock是可重入的实现

Lock 和 synchronized 的区别?

Lock接口中定义了一种无条件、可轮询的、定时的以及可中断的锁获取操作,所有加锁和解锁的方法都是显式的。

Lock接口提供了与synchronized相同的互斥性和内存可见性,而在加锁语义,调度算法,顺序保障和性能特性方面有所不同。

lock在哪些场景下使用?

  1. 轮询锁,可以解决死锁,tryLock()获取失败则返回,
  2. 定时锁和可中断的锁获取操作,tryLock(timeOut)等待超时返回,可中断
  3. 非块结构加锁(连锁式加锁或者锁耦合)
  4. 要求公平性的业务场景

Lock 性能比 synchronized 好?

在Java5.0中,ReentrantLock能提供更高的吞吐量,但在Java6中,二者的吞吐量非常接近

总的来说,两者基本性能都很奈斯

没有永远的好与坏

公平性

什么是公平锁和非公平锁?分别对应什么应有场景?

公平锁,必须要求排队,先进先出,会带来额外的阻塞和唤醒等额外的开销

  • 公平锁,必须要求排队,先进先出,会带来额外的阻塞和唤醒等额外的开销

  • 非公平锁,获取锁失败才加入排队,但会带来“饥饿”的可能

当持有锁的时间相对较长,或者请求锁的平局时间间隔较长,非公平锁带来的性能提升不会明显,如果公平锁更符合业务场景,那么应该使用公平锁

img

内置锁默认为非公平锁

在 synchronized 和 ReentrantLock 间选择?

当 synchronized 不适用才使用 ReentrantLock

读写锁

1
2
3
4
public interface ReadWriteLock {
Lock readLock();
Lock writeLock();
}

一个资源能同时被多个读操作访问,或者只能被一个写操作访问,但两者不能同时进行。

这句话很关键

读写锁交互实现策略:

  • 释放优先级:写锁释放时,其他线程是读优先,还是写优先,还是先来的优先
  • 读线程插队:锁被读线程持有,且有写线程在等待,后续读线程能否插队?能插队的性能更高,但是数据上可能会有问题。
  • 重入性:是否可重入,主要是写线程的重入
  • 降级:写锁保存的范围降低为读锁来保存,目的是为了增加并发性
  • 升级:不应该支持,会导致死锁(两个线程在获取读锁后,同时升级的话会死锁)

降级的案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class CachedData {
Object data;
volatile boolean cacheValid;
final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();

void processCachedData() {
rwl.readLock().lock();
if (!cacheValid) {
// 不能做升级操作
rwl.readLock().unlock();
rwl.writeLock().lock();
try {
// Recheck state because another thread might have
// acquired write lock and changed state before we did.
if (!cacheValid) {
data = ...
cacheValid = true;
}
// 可以做降低
rwl.readLock().lock();
} finally {
rwl.writeLock().unlock(); // Unlock write, still hold read
}
}

try {
use(data);
} finally {
rwl.readLock().unlock();
}
}
}

ReentrantWriteReadLock 的实现策略?

默认为非公平锁,释放优先级不确定,不允许读线程查询,可重入,支持降级,不支持升级

ReentrantWriteReadLock 和 ReentrantLock 的性能对比?

对于在多处理器系统上被频繁读取的数据结构,读 - 写锁能够提高性能。而在其他情况下,读 - 写锁的性能比独占锁的性能要略差一些,这是因为它们的复杂性更高

image-20200904111147087

本文标题:11显示锁

文章作者:Sun

发布时间:2020年09月04日 - 11:09

最后更新:2020年09月07日 - 11:09

原始链接:https://sunyi720.github.io/2020/09/04/Java并发编程/11显示锁/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。