目录
先看目录!!先看目录!!先看目录!!
1、按锁的性质分类:
互斥锁
- 定义:同一时间只允许一个线程访问共享资源
- 特点:强制串行访问,简单但是可能成为性能瓶颈
- 示例:Java中 synchronized关键字、ReentrantLock锁
- 适用场景:写操作频繁或临界区代码较长的场景。
读写锁
- 定义:分为读锁和写锁。读锁允许多线程并发读。写锁独占锁资源
- 读锁:共享锁
- 写锁:排他锁 (排他锁是互斥锁的一种特殊表现形式。)
- 特点:提升读多写少场景的性能
- 示例:ReentrantReadWriteLock
- 适用场景:读操作远多于写操作的场景(eg. 缓存)。
2、按线程调度机制分类:
自旋锁
- 定义:线程通过循环不断的尝试获取锁,不会立即进入阻塞状态。
- 特点:上下文切换开销减少,但是CPU的能耗会提升,可能到只CPU空转。
- 示例:CAS中的 AtomicInteger。
- 适用场景:锁竞争时间短的场景(eg.轻量级操作)。
阻塞锁
- 定义:线程获取锁失败就立即进入阻塞状态(由操作系统调度唤醒)。
- 特点:减少CPU空转,但是上下文切换的开销增加。
- 示例:当锁竞争激烈时synchronized就会升级为阻塞锁。
- 适用场景:锁持有时间较长的场景。
3、按并发策略分类:
悲观锁
- 定义:假设并发冲突频繁,并且数据冲突是不可避免的,线程访问数据前提前加锁。
- 特点:安全,性能低
- 示例:synchronized,数据库行锁
- 适用场景:
- 1、高并发切数据竞争激烈:当多个事务需要同时修改一个数据时,悲观锁可以保证数据在任一个时刻只被一个事务访问和修改。避免数据不一致问题和脏读。
- 2、数据一致性要求极高。
- 3、写操作频繁:更有效的保护数据
- 4、事务执行时间长:确保事务执行期间不会有其他事务干扰,数据被其他事务修改,导致数据不一致和脏读。
乐观锁
- 定义:假设并发冲突概率低,通过版本号或CAS机制,更新数据(确保数据一致性)。
- 特点:无锁涉及,需要处理更新失败(重试或者回滚)
- 示例:AtomicInteger
- 适用场景:写操作少;重试成本低;数据冲突少;系统能容忍一定程度的失败。
4、按可重入性分类:
可重入锁
- 定义:允许同一线程多次获取同一把锁(递归调用不会死锁)。
当线程获取到A锁,在获取之后尝试再次获取A锁时可以直接拿到的。
- 示例:ReentrantLock、Synchronized
- 优势:简化递归逻辑和和复杂同步代码的设计
不可重入锁
- 定义:线程重复获取自己持有的锁有会导致死锁
当线程获取到A锁,在获取之后尝试再次获取A锁,无法获取到,因为A锁被当前线程占着,需要等待自己释放锁后,再获取锁。
- 示例:简单的自旋锁实现。
5、按公平性分类:
公平锁
- 定义:按照请求顺序分配锁资源(先到先得)。
线程A获取到了锁资源,线程B没有拿到,线程B去排队,线程C来了,锁被A持有,同时线程B在排队。直接排到B的后面,等待B拿到锁资源或者是B取消后,才可以尝试去竞争锁资源。
- 特点:避免线程饥饿,但吞吐量较低。
- 示例:ReentrantLock(true)
非公平锁
- 定义:允许插队,新请求的线程可以直接尝试获取锁资源。
线程A获取到了锁资源,线程B没有拿到,线程B去排队,线程C来了,先竞争一波,
- 线程C拿到了锁资源 -- 插队成功
- 线程C 没有拿到锁资源-- 插队失败,依然要排到线程B 的后面,等待线程B拿到锁资源或者B取消后,才可以继续竞争锁资源
- 特点:高吞吐,但是可能会导致某些线程等待时间过长。
- 示例:ReentrantLock() (默认非公平)。Synchronized
公平锁绝对公平,非公平锁没有那么的不公平。
6、按作用范围分类
对象锁
类锁
分布式锁
这部分内容会在Synchronized 部分讲到 -->跳转链接
7、其他分类:
偏向锁、轻量级锁、重量级锁(java的锁优化)
分段锁
条件锁
这部分内容会在Synchronized 部分讲到 --> 跳转链接
问题1:排他锁、互斥锁、共享锁、读写锁。这四把锁的关系是什么样的?
读写锁、排他锁、共享锁
- 读写锁的读锁 = 共享锁:允许多线程并发读
- 读写锁的写锁 = 排他锁:保证写操作的独占性
- 读写锁是一个复合机制:通过共享锁和排他锁的写作,平衡了并发性能和数据一致性。
排他锁和互斥锁
- 排他锁是互斥锁的一种特殊形式,专用于读写锁中的写操作。
- 互斥锁是更官方的概念,适用于所有需要独占访问的场景。
- 两者本质都是保证资源的独占性。但排他锁通过读写分离机制优化了并发性能。
维度 互斥锁(Mutex) 排他锁(Exclusive Lock) 定位 通用锁机制,强调互斥访问 特定场景下的互斥锁(专用于写操作) 应用场景 任何需要互斥的场景 读写锁中的写操作 锁粒度 粗粒度(不区分读/写) 细粒度(与共享锁配合,区分读/写) 典型实现 synchronized
、ReentrantLock
ReentrantReadWriteLock.WriteLock
与共享锁关系 不涉及共享锁 必须与共享锁(读锁)成对使用