Skip to content

锁的分类

1. 乐观锁 vs 悲观锁

  • 悲观锁:认为数据在并发操作中很可能被其他线程修改,因此在访问数据之前先加锁,确保数据在操作期间不会被其他线程修改。例如,synchronized关键字和ReentrantLock就是悲观锁的实现。
  • 乐观锁:认为数据在并发操作中很少被修改,因此不会先加锁,而是在更新数据时检查在此期间是否有其他线程修改了数据。通常使用版本号或CAS(Compare and Swap)操作来实现。例如,Java中的AtomicInteger就是使用CAS实现的乐观锁。

2. 独占锁(排他锁) vs 共享锁

  • 独占锁:一次只能被一个线程持有。例如,ReentrantLock就是独占锁。
  • 共享锁:允许多个线程同时持有。例如,ReadWriteLock中的读锁就是共享锁。

3. 可重入锁 vs 非可重入锁

  • 可重入锁:同一个线程可以多次获取同一把锁。例如,synchronized和ReentrantLock都是可重入锁。
  • 非可重入锁:同一个线程多次获取同一把锁会阻塞。Java中很少使用非可重入锁。

4. 公平锁 vs 非公平锁

  • 公平锁:按照线程请求锁的顺序来获取锁,即先到先得。
  • 非公平锁:不按照请求顺序,允许插队。synchronized是非公平锁,ReentrantLock既可以公平也可以非公平。

5. 其他锁

  • 自旋锁:线程在获取锁时,如果锁被占用,不会立即阻塞,而是循环检查锁是否被释放,适用于锁占用时间很短的场景。
  • 分段锁:将数据分段,每段一把锁,例如ConcurrentHashMap中的分段锁。
  • 读写锁:读锁共享,写锁独占,例如ReadWriteLock。

Redis分布式锁的定位

  • 乐观锁 vs 悲观锁:Redis分布式锁通常被实现为悲观锁,因为它假定在访问共享资源时会发生冲突,所以每次访问资源时都会先获取锁,确保同一时间只有一个客户端可以访问。

  • 公平锁 vs 非公平锁:标准的Redis分布式锁(如使用SETNX命令)是非公平的,因为多个客户端同时请求锁时,谁先抢到锁是随机的,并不按照请求的顺序获取。但是,可以通过一些机制(如使用队列)实现公平的分布式锁,但常见的实现是非公平的。

  • 可重入锁 vs 不可重入锁:基本的Redis分布式锁通常是不可重入的,因为它在实现时没有记录持有锁的客户端线程,同一个客户端再次请求锁时会被阻塞。但是,我们可以通过记录锁的持有者和计数器来实现可重入的Redis分布式锁。

  • 独占锁 vs 共享锁:Redis分布式锁通常是独占锁(排他锁),因为一旦某个客户端获取了锁,其他客户端都无法再获取,直到锁被释放。Redis也支持读写锁,可以通过多个键和Lua脚本实现共享锁(读锁)和独占锁(写锁)。

所以,我们可以将常见的Redis分布式锁归类为:悲观锁、非公平锁、不可重入锁(但可实现可重入)、独占锁。但是,需要注意的是,Redis分布式锁的具体实现可以有不同的特性,比如Redisson库中的分布式锁就实现了可重入、公平锁等特性。因此,具体属于哪一类还要看实现方式。

页脚:版权前显示的信息