面试题答案
一键面试1. 粗粒度锁
-
策略描述:对整个资源或较大范围的操作加锁,一个锁保护多个操作或大量数据。例如在一个包含多个方法操作共享数据的类中,使用
synchronized
修饰整个类或一个大的方法块,这样其他线程访问该类任何涉及共享数据的操作都需获取这把锁。 -
优点:
- 实现简单:只需在关键位置加一把锁,代码逻辑相对清晰,易于理解和维护。
- 锁竞争开销低:锁的获取和释放次数少,减少了因频繁加锁、解锁带来的性能开销。
-
缺点:
- 并发度低:同一时间只有一个线程能执行被锁保护的代码,其他线程都需等待,即使不同线程操作的是不相关部分数据,也会互相阻塞,影响系统整体性能。
- 死锁风险高:当多个线程获取锁的顺序不一致时,容易产生死锁。
-
应用场景:适用于对共享资源操作频率较低,且操作时间较短的场景,例如初始化操作等。
2. 细粒度锁
-
策略描述:将锁的范围细化,对不同部分的数据或较小的操作分别加锁。例如在一个包含多个成员变量的类中,每个变量或相关的一小部分操作都有自己独立的锁。
-
优点:
- 并发度高:不同线程可以同时访问不同锁保护的资源,提高了系统的并发处理能力。
- 灵活性高:可以根据不同的业务需求,对不同的数据块或操作设置不同的锁机制,如读写锁等。
-
缺点:
- 实现复杂:需要仔细设计锁的划分和管理,否则容易出现死锁、数据不一致等问题。
- 锁竞争开销高:由于锁的数量增多,线程获取和释放锁的频率增加,带来额外的性能开销。
-
应用场景:适用于对共享资源操作频繁,且操作可以细粒度划分的场景,如数据库的行级锁。
3. 读写锁
-
策略描述:区分读操作和写操作,读操作可以共享锁(多个读线程可以同时持有读锁),写操作独占锁(只有一个写线程可以持有写锁)。在Java中可以使用
ReentrantReadWriteLock
实现。 -
优点:
- 提高读并发性能:读操作不修改数据,多个读线程同时进行不会产生数据冲突,所以可以共享锁,大大提高了读操作的并发度。
- 保证数据一致性:写操作时独占锁,避免了写操作期间其他读或写操作对数据的干扰,保证了数据的一致性。
-
缺点:
- 增加锁管理复杂度:需要分别处理读锁和写锁的获取与释放,增加了代码的复杂性。
- 可能产生写操作饥饿:如果读操作频繁,写操作可能长时间无法获取锁,导致写操作饥饿。
-
应用场景:适用于读多写少的场景,如缓存系统,大量线程读取缓存数据,偶尔有线程更新缓存。
4. 分段锁
-
策略描述:将一个大的数据结构或资源分成多个段,每个段有自己的锁。例如
ConcurrentHashMap
中,将哈希表分成多个段(Segment),每个段都有一把锁,不同线程可以同时对不同段进行操作。 -
优点:
- 提高并发度:在一定程度上避免了对整个数据结构加锁带来的性能瓶颈,不同线程可以同时操作不同段的数据,提高了并发处理能力。
- 减少锁竞争:相比于对整个数据结构加锁,锁的粒度更小,锁竞争的概率降低。
-
缺点:
- 增加内存开销:每个段都需要额外的锁资源,增加了内存开销。
- 实现复杂:需要合理划分段,并且处理好段之间可能存在的边界问题,实现相对复杂。
-
应用场景:适用于对大型数据结构操作频繁且需要较高并发度的场景,如大规模缓存系统的实现。