Java多线程和高并发(二)

volatile关键字

volatile的字面意思是adj. 挥发性的;不稳定的;爆炸性的;反复无常的,它的作用是保住线程可见性,并且禁止指令的重排。

在默认情况下,堆内存中的变量,在被多个线程使用时,每个线程会分别复制一个副本到CPU的缓存中,即这个线程的工作空间中,这个变量在线程间是不可见的,如果共享内存中的值有变化,线程不会马上感知到其变化。

如果变量被volatile修饰,则可以保证其线程间的可见性,即一个线程操作这个变量发生改变,其他线程立即可见。其实现原理是CPU的基于失效的缓存一致性协议(MESI)。

Volatile还有一个作用是禁止指令重排序。重排序产生的原因是CPU为了提高效率,会并发执行指令。编译器把代码编译成指令后,CPU可能会将其顺序重排,这会在某些情况导致下导致结果与预想的不一致。

锁优化

锁的细化:只在需要保证原子性的代码上加上synchronized。

但是并不是越细余越好,要合理规划,减少线程争用。

一个细节:

如果使用对象作为锁的时候,这个对象要用final修饰,防止对象发生导致并发出现问题。

CAS

Java中提供了一些线程安全的类,比如AtomicInteger等,内部使用Unsafe.java,其中提供了一系列的compareAndSwap(JDK1.8)方法,可以方便的使用。

其实现原理就是CAS操作,即Compare and set,在一般情况下,想保证修改值时线程安全,就要加锁,使用CAS操作时,要先比较期望修改的值与原值是否相同,相同则修改,如果发现值发生变化,则不改变,进行重试。至于比较的指令,由CPU原语保证线程安全。

ABA问题

ABA问题导致的原因是如果其他线程将变量修改后,又修改为期望值了,比如A改成B,又改成A,则会导致比较判断时无法察觉发生了变化。这个问题加上版本号比较即可解决。

标签:

发表评论

电子邮件地址不会被公开。 必填项已用*标注