解释一下什么是乐观锁、悲观锁、自旋锁、互斥锁、读写锁、排他锁、共享锁、统一锁、分段锁?
定义角度不同,通常把(乐观锁、悲观锁)、(自旋锁、互斥锁)、(读写锁、排他锁、共享锁)、(统一锁、分段锁)分组理解
1. 乐观锁(Optimistic Locking)
- 定义:乐观锁机制采取了更加宽松的加锁机制,认为数据的变动不会太频繁。它通常基于数据版本(Version)记录机制实现,通过为数据增加一个版本标识来避免冲突。
- 应用场景:适合读多写少的场景,能够提升系统整体性能,避免长事务中的数据库加锁开销。
- 优点:提高了系统的并发性,减少了锁的开销。
- 缺点:如果数据更新频繁,可能会导致大量数据冲突,增加重试成本。
- 实现方式:在数据库表中增加一个“version”字段,每次更新数据时,将版本号加一,并检查当前版本号是否与提交时的版本号一致。
2. 悲观锁(Pessimistic Locking)
- 定义:悲观锁认为被保护的数据是极其不安全的,每个时刻都有可能被其他进程修改。因此,它会先对数据进行加锁,然后才能进行操作。
- 应用场景:适合写操作较多的场景,能够确保数据的一致性和完整性。
- 优点:能够有效地防止数据冲突,保证数据的准确性。
-缺点:可能会降低系统的并发性,因为当一个事务持有锁时,其他事务只能等待。 - 实现方式:数据库中的行锁、表锁、读锁、写锁以及synchronized关键字实现的锁都可以视为悲观锁的一种形式。
3. 自旋锁(Spin Lock)
- 定义:自旋锁是专为防止多处理器并发而引入的一种锁,它在内核中大量应用于中断处理等部分。自旋锁在尝试获取锁时,如果锁已被占用,则循环等待直到锁被释放。
- 应用场景:适合锁持有时间非常短的场景,如中断处理、底半部等。
- 优点:避免了线程在获取锁时的睡眠和唤醒开销,提高了效率。
- 缺点:如果锁持有时间过长,会导致CPU资源的浪费,甚至可能引发死锁。
- 实现方式:通过特定的原子操作(如test-and-set)来实现对锁的获取和释放。
4. 互斥锁(Mutual Exclusion)
- 定义:互斥锁是一种用于保护共享资源的锁,它可以保证在任意时刻只有一个线程能够访问共享资源,从而避免了多个线程同时对共享资源进行写操作导致的数据不一致问题。其工作原理主要涉及两个关键操作:加锁(Lock)和解锁(Unlock)。
当已经有一个线程加锁后,其他线程加锁则就会失败,互斥锁和自旋锁对于加锁失败后的处理方式是不一样的:
互斥锁加锁失败后,线程会释放 CPU ,给其他线程;
自旋锁加锁失败后,线程会忙等待,直到它拿到锁;
5. 读写锁(Read-Write Lock)
- 定义:将共享资源的访问者分为读者和写者。读者可以同时访问共享资源,但写者在写入时需要独占访问权。读写锁维护了一对锁,一个读锁和一个写锁,读锁是一个共享锁,写锁是一个排它锁,在读操作时获取读锁,写操作时获取写锁。
- 应用场景:读写锁适用于能明确区分读操作和写操作的场景。
- 优点:允许多个读者同时访问共享资源,提高了系统的并发性。
- 缺点:当写者较多时,可能会导致写者之间的冲突和等待。
- 实现方式:通过维护一个读者计数器和一个写者标志位来实现对读写操作的控制。
6. 排他锁(Exclusive Lock)
- 定义:排他锁又称为写锁、独占锁,是一种基本的锁类型。它允许事务对数据对象进行读取和修改,同时阻止其他任何事务对同一数据对象进行访问。
- 应用场景:适合需要独占访问共享资源的场景。
- 优点:能够确保数据的完整性和一致性。
- 缺点:降低了系统的并发性。
7. 共享锁(Shared Lock)
- 定义:共享锁又称为读锁,它允许事务对数据对象进行读取操作,但阻止其他事务对该数据对象进行写操作。
- 应用场景:适合多个事务需要同时读取同一数据对象的场景。
- 优点:提高了系统的并发性,允许多个事务同时读取同一数据对象。
- 缺点:在共享锁持有期间,其他事务无法对数据进行写操作。
8. 统一锁(Unified Lock)
- 定义:统一锁是一种综合了排他锁和共享锁的锁机制,它可以根据需要切换到排他模式或共享模式。(大粒度)
- 应用场景:适用于需要根据不同情况灵活切换锁模式的场景。
- 特点:具有排他锁和共享锁的双重特性,能够根据需要进行灵活切换。
9. 分段锁(Segment Lock)
- 定义:分段锁是一种将数据划分成多个部分,并为每个部分分配一个锁的机制。(小粒度)
- 应用场景:适用于需要处理大量数据且数据可以分段的场景,如数据库中的分区表。
- 特点:通过分段锁可以减少锁的竞争,提高系统的并发性能。不同的线程可以同时访问不同的数据段而不会产生冲突。
- ConcurrentHashMap
总结
互斥锁和自旋锁都是最基本的锁,读写锁可以根据场景来选择这两种锁其中的一个进行实现。
另外,互斥锁、自旋锁、读写锁都属于悲观锁,悲观锁认为并发访问共享资源时,冲突概率可能非常高,所以在访问共享资源前,都需要先加锁。
乐观锁、悲观锁是从锁的心态出发,和业务场景高度相关。
统一锁、分段锁是从锁的粒度出发,全局和局部锁的划分。