- CAS背后没有加锁,不需要加锁,背后需要靠cpu原语来实现
- 已学:synchronized、volatile、Atomic、CAS
- 继续学Atomic
- 无锁操作效率更高
- 多线程对一个数递增的解决方案(经常遇到)
- 普通变量加锁
- AtomicInt类
- LongAdder类(LongAccumulator类)
- 上述三种方式的效率高低
- synchronized一般比Atomic高,但也有差不多的时候
- 粗糙的测试方式(算间隔时间)
- JMS测试===>专业、科学
- LongAdder(分段锁) > 一般Atomic(无锁) > synchronized(锁升级、锁膨胀 无锁->偏向锁->自旋锁->重量级锁)(将线程数调小或循环数少了LongAdder未必有优势)
- 实际中用哪种要考虑一下将来的并发度有多高(线程的并发度会影响这些方法的效率)
- 最好进行压测,或者性能测试
- 并发度影响性能的原因:
- CAS与synchronized选择时:线程数多、执行时间长选synchronized;线程数少、执行时间短选CAS
- LongAdder比Atomic快的原因:LongAdder底层是用的分段锁
LongAdder实现原理
- 分段锁
- 线程数少的时候LongAdder没有什么优势,并发度高的时候LongAdder的优势就出来了
- LongAdder使用一个数组,将值放到数组中,刚开始都是0;一共有1000个线程,将250个线程一组锁起来,每一个都往上递增,最后算出结果之后,将结果加起来,加起来的总的就得到了最终的和
- 分段锁也是CAS操作(有可能会问)===>为什么用CAS,因为线程数少并且CAS执行效率相对较高
LongAdder 是 LongAccumulator 的一种特殊形式
- LongAdder | LongAccumulator简介
- LongAccumulator用得更少!
🤏随想
- java object layout===>jol(现实java对象在内存中的结构:markword、class pointer、instance data、对齐填充位)
- jvm自增陷阱,count = count++:
- 首先执行count=count (count=0)JVM会把count放到临时变量区
- 再执行count++
- 当++执行完了之后,jvm就会把在临时变量区的count放回来,但是这个时候count还是0
- 注:inc指令是直接发生在局部变量表中的,而不是在栈中