java中的锁 按不同维度 有哪几种类型
1. 基于获取锁的公平性分类
公平锁(Fair Lock):线程会按照请求锁的先后顺序来获取锁,避免某些线程长期等待。像
`ReentrantLock`在设置为公平锁模式时,就会遵循先到先得的原则。
非公平锁(Non-Fair Lock):线程获取锁无需遵循特定顺序,有可能后请求的线程反而先获得锁,
这样虽然会导致锁竞争加剧,但能减少线程切换带来的开销。例如`synchronized`关键字和默认的
`ReentrantLock`都属于非公平锁。
2. 按照锁的状态变化分类
可重入锁(Reentrant Lock):同一线程可以多次获取同一把锁,而不会出现死锁的情况。
`synchronized`和`ReentrantLock`都具备可重入的特性。
不可重入锁(Non-Reentrant Lock):同一线程在未释放锁之前,无法再次获取该锁,容易引发死
锁问题。在Java中,这种锁比较少见。
3. 依据锁的共享性分类
独占锁(Exclusive Lock):也被称为互斥锁,同一时刻只允许一个线程持有锁,像`synchronized`
和`ReentrantLock`就属于此类。
共享锁(Shared Lock):同一时刻允许多个线程同时持有锁,比如`ReentrantReadWriteLock`中的
读锁。
4. 从锁的实现方式分类
内置锁(Intrinsic Lock):通过`synchronized`关键字实现,由JVM负责管理锁的获取和释放。
显式锁(Explicit Lock):基于`java.util.concurrent.locks.Lock`接口实现,例如`ReentrantLock`,
需要手动控制锁的获取和释放。
5. 按照锁的优化技术分类
偏向锁(Biased Lock):在单线程环境下,锁会偏向第一个获取它的线程,当该线程再次获取锁
时,无需进行同步操作,从而提升性能。
轻量级锁(Lightweight Lock):当锁处于轻量级状态时,竞争线程不会被阻塞,而是通过自旋的方
式尝试获取锁,避免了线程切换的开销。
重量级锁(Heavyweight Lock):依赖操作系统的互斥量(Mutex)来实现,线程竞争锁时会被阻
塞,适用于锁竞争激烈的场景。
6. 其他特殊类型的锁
读写锁(ReadWrite Lock):将锁分为读锁和写锁,允许多个线程同时读取共享资源,但写操作具
有排他性,例如`ReentrantReadWriteLock`。
分段锁(Striped Lock):把锁分成多个部分,不同的线程可以同时访问不同的分段,从而提高并发
性能,`ConcurrentHashMap`在JDK 7及以前的版本中使用了这种锁。
乐观锁(Optimistic Lock):不会真正加锁,而是在更新数据时检查是否有其他线程对数据进行了
修改,通常通过版本号机制或CAS(Compare-and-Swap)操作来实现。
悲观锁(Pessimistic Lock):假设会发生冲突,在操作数据前先加锁,例如`synchronized`和
`ReentrantLock`。
总结
Java中的锁机制设计十分灵活,不同类型的锁适用于不同的场景。你可以根据实际需求,从公平性、共
享性、实现方式等多个维度来选择合适的锁,以平衡性能和线程安全。
本文整理自实践经验,如有问题欢迎交流讨论。