并发与高并发编程实战04--线程安全性之原子性

定义:当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些进程将如何交替执行,并且在主调代码中不需要任何额外的同步或者协同,这个类都能表现出正确的行为,那么就称这个类是线程安全的.

原子性:提供了互斥访问,同一个时刻只能有一个线程来对它操作

原子性核心代码compareAndSwapInt 简称CAS。不断进行do-while循环直到,当前的值与底层的相等,才进行相加操作

并发与高并发编程实战04--线程安全性之原子性_第1张图片

可见性:一个线程对主内存的修改可以及时的被其他线程观察到

有序性: 一个线程观察其他线程中的指令执行顺序,由于指令重排序的存在,该观察结果一般杂乱无序

问题1

有了AtomicLong为什么还需要LongAdder这个类?

LongAdder是jdk1.8里面的类,

AtomicLong的原理是依靠底层的cas来保障原子性的更新数据,在要添加或者减少的时候,会使用死循环不断地cas到特定的值,从而达到更新数据的目的,高并发的时候修改数据失败的概率很高,一旦失败就要再次循环,循环就会影响性能!!!

对于普通类型的long和double类型的变量,jvm允许64的读操作或者写操作拆成两个32的读操作或者写操作.

LongAdder在AtomicLong的基础上将单点的更新压力分散到各个节点,其实现原理是通过hash等算法将数据分割成数组的形式,最后再叠加。当前对象的实际值由所有的cell累加而成。在低并发的时候通过对base的直接更新可以很好的保障和AtomicLong的性能基本保持一致,而在高并发的时候通过分散提高了性能。 

缺点是LongAdder在统计的时候如果有并发更新,可能导致统计的数据有误差

总结

序列号生成等需要准确的数据或者低并发用AtomicLong

高并发用LongAdder

ps:但是我在实际测试的时候,200000的并发发现两者花费时间差距不大,不知道是不是LongAdder真的适合高并发,代码这东西讲白了最后要操作硬件的,思路虽然是对的,可能实际结果并不是想的那样,程序员写的代码都会有Bug的,就算他再大神!

场景1下图所示 这个方法可以保证同一代码同一时间只有一个线程可以执行!!!比如我们经常会写一个标志位 先设置true 执行完后再设置成false。

并发与高并发编程实战04--线程安全性之原子性_第2张图片

并发与高并发编程实战04--线程安全性之原子性_第3张图片


原子性对比

synchronized:不可中断锁,适合竞争不激烈,可读性好

Lock:可中断锁,多样化同步,竞争激烈时能维持常态

Atomic:竞争激烈时能维持常态,比Lock性能好,只能同步一个值.

你可能感兴趣的:(并发与高并发)