第13章 线程安全与锁优化

一、线程安全
1. 线程安全级别有5种:
不可变,绝对线程安全,相对线程安全,线程兼容,线程对立

(1)不可变
保证对象状态不可变是最简单最纯粹的安全

(2) 绝对线程安全
在线程之间不需要使用任何额外的手段就可以实现线程安全,绝对线程安全很难达到,一般都是相对线程安全

(3)相对线程安全
在一个线程内部或一个对象内部是线程安全的,但是多线程之间需要额外的手段保证线程安全

(4)线程兼容
对象本身不是线程安全的,但是可以使用同步手段保证线程安全,平常所说一个类不是线程安全的,大多数指的是这种

(5)线程对立
不管调用端是否采取了同步措施,都无法在多线程环境中并发使用的代码

2. 线程安全(线程同步)的实现方法:
(1)阻塞同步:synchronized和ReentrantLock
(2)非阻塞同步:基于冲突检测的CAS操作
(3)无同步方案

(1)阻塞同步
阻塞同步的方法主要有两种:
synchronized和java.util.concurrent包中的ReentrantLock
缺点:
(1)进行线程阻塞和唤醒会带来性能问题,因为需要在用户态和核心态之间切换,消耗CPU时间
(2)是一种悲观锁,在可能发生问题的地方都加锁,而不管实际是否真的需要加锁

在性能上synchronized和ReentrantLock基本持平,只是在功能上ReentrantLock更全面
因此在满足需求的情况下,优先考虑使用synchronized实现同步

(2)非阻塞同步
基于冲突检测的非阻塞同步,是一种乐观的并发策略
需要操作和冲突检测具有原子性,语义上需要多次操作的行为只通过一条指令完成,使用CAS,由硬件实现

二、锁优化
1. 自旋锁与自适应自旋
(1)自旋锁
并不阻塞线程,而是让线程执行一个忙循环,依然占有CPU
确定一个自旋次数,如果自旋超过限定的次数仍然没有获得锁,就使用传统的方式挂起线程

(2)自适应自旋
不固定自旋次数,而是根据上次自旋时间以及锁的拥有者状态来决定
如果上次自旋获得过锁,并且持有锁的线程正在运行中,那么虚拟机就会认为这次自旋也有可能成功,进而允许自旋等待更长的时间
如果对于某个锁,自旋很少成功获得过,那么在以后要获得这个锁时,可能会省略掉自旋,而是直接挂起线程

2. 锁消除
即时编译器在编译时将会对不需要进行同步的代码进行锁消除
判断能否进行锁消除的主要依据就是对象是否会发生逃逸(方法逃逸和线程逃逸)

3. 锁粗化
扩大锁的范围,使得对小范围的代码不会频繁地进行加锁
比如需要循环进行A操作,而A本身是加锁的,就可以把锁扩大到整个循环外面
又比如进行A,B,C操作,ABC都是加锁的,可以把锁扩大到ABC外面
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值