在Java中可以通过锁和循环CAS操作的方式来实现原子操作。
一,使用循环CAS实现原子操作
JVM中的CAS操作是利用了处理器提供的 CMPXCHG 指令实现的。自旋CAS实现的基本思路就是循环进行CAS操作,直到成功为止。CAS是Compare And Swap的缩写,其操作需要输入两个值,一个旧值,一个新值,在操作期间比较旧值有没有发生改变,如果没发生,才交换成新值,发生了变化则不交换。
CAS操作虽然很高效地解决了原子操作,但是仍有三大问题:
1)ABA问题。如果CAS在操作旧值的时候,旧值原来是A,变成了B,又变回了A,CAS会发现它的值没有发生变化,但实际上却变化了,这一操作便不是原子操作。目前ABA问题的解决思路是使用版本号。在变量前面追加版本号,由A-B-A变成1A-2B-3A。
2)循环时间长开销大。自旋CAS如果长时间不成功,会给CPU带来非常大的执行开销。
3)只能保证一个共享变量的原子操作。当对一个共享变量执行操作时,我们可以使用共享CAS的方式来保证原子操作,但对多个共享变量操作时,无法保证操作的原子性。这时可以将多个共享变量合并成一个共享变量来操作。
二,使用锁机制实现原子操作
锁机制保证了只有获得锁的线程才能够操作锁定的内存区域。JVM中的轻量级锁和重量级锁都使用了循环CAS操作来获取锁,退出是同样使用循环CAS退出锁。