一. 悲观锁、乐观锁
1、悲观锁认为共享资源并发操作一定会出现问题,使用synchronized关键字或者lock接口特性加锁;
2、乐观锁认为不加锁给并发操作带来性能提升,常采用CAS(Compare比较 And Swap交换)自旋锁;典例就是并发原子类,通过CAS自旋来更新值
二. 公平锁、非公平锁
1、公平锁指多个线程按照申请锁顺序依次获取锁;
2、非公平锁不考虑排队等待问题,直接尝试获取,获取不到自动队尾等待;(随机就近原则)
synchronized是非公平锁,ReentrantLock默认的lock是非公平锁;
三. 独占锁、共享锁
独占锁是一种悲观锁策略,每次只能一个线程持有锁
synchronized,ReentrantLock都是独占锁,
但对于ReadWriteLock接口而言,读是共享,写是独享,在lock的实现中通过AQS(抽象队列同步器)实现;
四. 可重入锁(递归锁)
指的是同一个线程,外层函数获得锁后,内层函数仍然有获取该锁的代码(即内层函数自动获取锁),但不受影响;
synchronized,ReentrantLock都是可重入锁;最大好处能避免一定程度的死锁;
五. 自旋锁
如果持有锁线程短时间内释放锁,那么等待竞争锁的线程就不需要做内核态和用户态之间的切换,进入阻塞挂起状态,
只需要等一等(自旋)一会等持有锁的线程释放后立即获取,避免了用户线程和内核的切换消耗,但是占用cpu;
底层采用CAS来保证原子性,自旋锁获取锁时不会阻塞,而是通过不断的while循环的方法尝试获取锁;
jdk1.7后:去掉参数,由jvm控制;java.util.concurrent包下几乎都是利用自旋锁;
六. 分段锁
分段锁是一种思想,并非实际锁。典型的ConcurrentHashMap.
七. 偏向锁、轻量级锁、重量级锁
锁的状态四种:无锁状态、偏向锁、轻量级锁、重量级锁【锁的状态是通过对象监视器在对象头中字段来表明的】
锁的状态只有升级,没有降级
偏向锁: 一段代码一直被同一个线程访问,那么该线程就会自动获取锁
轻量级锁: 当锁是偏向锁的时候,被另一个线程访问,偏向锁就会升级为轻量级锁,其他线程会通过自旋方式尝试获取锁,不会阻塞,提高性能
重量级锁: 当轻量级锁自旋超过一定次数,或者有三个线程来访问时,轻量级锁膨胀为重量级. 重量级锁除了拥有锁的线程以外的线程都阻塞,防止cpu空转
偏向锁,轻量级锁都是乐观锁,重量级锁时悲观锁