ABA问题:
假如有两个线程1,2;
cas下:1.线程取值完等待,2线程取值并把A改成B,有把B改成A,这是1线程执行会任务A还是原来的A没有发生改变,如果不在乎中间结果,只看收尾,那么没必要解决ABA问题
如何解决?
使用AtomicStampedRefererce,加版本号
代码演示如下:
package Volatile;import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicStampedReference;/*** ABA问题的解决办法 AtomicStampedReference 时间戳原子引用·*/
public class ABA {static AtomicReference<Integer> atomicReference = new AtomicReference<>(100);static AtomicStampedReference<Integer> atomicStampedReference = new AtomicStampedReference<>(100,1);public static void main(String []args){System.out.println("==========以下是ABA问题的产生=======");new Thread(()->{atomicReference.compareAndSet(100,101);atomicReference.compareAndSet(101,100);},"t1").start();new Thread(()->{//暂停1秒t2线程,保证t1完成一次ABAtry {TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace();}System.out.println(atomicReference.compareAndSet(100,2019)+"\t"+atomicReference.get());},"t2").start();try {TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace();}System.out.println("=========以下是ABA问题的解决==========");new Thread(()->{int stamp = atomicStampedReference.getStamp();System.out.println(Thread.currentThread().getName()+"\t第一次版本号:"+atomicStampedReference.getStamp());//暂停1秒t3线程,让t4也获取到一样的stamptry {TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace();}atomicStampedReference.compareAndSet(100,101,atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1);System.out.println(Thread.currentThread().getName()+"\t第二次版本号:"+atomicStampedReference.getStamp());atomicStampedReference.compareAndSet(101,100,atomicStampedReference.getStamp(),atomicStampedReference.getStamp()+1);System.out.println(Thread.currentThread().getName()+"\t第三次版本号:"+atomicStampedReference.getStamp());},"t3").start();new Thread(()->{int stamp = atomicStampedReference.getStamp();System.out.println(Thread.currentThread().getName()+"\t第一次版本号:"+atomicStampedReference.getStamp());//暂停1秒t3线程try {TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace();}boolean result = atomicStampedReference.compareAndSet(100, 2019, stamp, stamp + 1);System.out.println(Thread.currentThread().getName()+"\t修改功否:"+result);System.out.println(Thread.currentThread().getName()+"\t当前实际最新值:"+atomicStampedReference.getReference());},"t4").start();}
}