- 乐观锁&悲观锁
- 悲观锁:获取数据时加锁,(synchronized关键字、Lock实现类)
- 乐观锁:使用数据时不加锁,更新时判断之前是否有其他线程更新数据,(CAS算法)
- CAS(Compare And Swap):
- 无锁算法,实现线程的变量同步
- java.util.concurrent包中的原子类
- 实现方法:
- 需要读写的内存值V
- 进行比较的A
- 要写入的新值B
- 存在的问题:
- ABA问题
- 循环时间长、开销大
- 只能保证对一个共享变量的原子操作
- 自旋锁&适应性自旋锁
- 自旋锁:
- 同步资源锁定时间短,避免线程切换导致的开销,让后面请求锁的线程等待而进行自旋
- 缺点:浪费处理器资源
- 适应性自旋锁:
- 自旋时间不固定,根据同一个锁上一次的等待时间和锁拥有者运行状态决定
- 自旋很少成功,则阻塞线程
- 无锁&偏向锁&轻量级锁&重量级锁
- 针对synchronized的锁状态
- 重量级锁:依赖操作系统的Mutex Lock(互斥锁)
- 偏向锁:一段同步代码一直被一个线程所访问,不存在线程竞争,自动获取锁,不通过CAS加解锁
- 轻量级锁:当锁是偏向锁时,被其他线程访问时变成轻量级锁,通过自旋的方式获取锁,不会阻塞
- 总结:偏向锁通过对比Mark Word解决加锁问题,避免CAS操作;轻量级锁通过CAS操作和自旋解决加锁问题,避免线程阻塞;重量级锁将其他线程阻塞
- 公平锁&非公平锁
- 公平锁:按照申请锁的顺序排队获取锁,不会饿死,吞吐效率低
- 非公平锁:获取锁时获取不到排队,可用直接获取,排队线程可能饿死
- 可重入锁&非可重入锁
- 可重入锁:
- 同一个线程外层方法获取锁后,内层方法自动获取锁(ReentrantLock、synchronized)
- 非可重入锁:
- 重复调用同步资源时会死锁
- 独享锁&共享锁
- 独享锁(互斥锁、排他锁)
- 对数据A加锁后,其他线程不能对A加其他类型的锁,锁一次只能被一个线程持有
- synchronized、ReentrantLock
- 共享锁
- 可以被多个线程持有,多个线程可以同时对A加共享锁,共享锁只读不写
- ReentrantReadWriteLock