多线程-java 比较然后设置compareAndSet

731 阅读2分钟

核心类

是Unsafe

核心方法

compareAndSet(旧值,新值);

如何应用?

1.Unsafe.compareAndSet(旧值,新值);
2.自己实现工具类 //必须包含一个数据,这个数据就是旧值

最核心的东西,就是上面两个东西。

代码

自定义工具类{
    private Unsafe unsafe; //提供比较然后设置方法的功能
    private volatile int oldValue; //保存旧值
}

具体步骤

1.读取旧值  //自定义工具类.oldValue;  
2.比较然后设置  //Unsafe.compareAndSet(旧值,新值);   
3.true,就设置新的值;false,就不设置 //Unsafe.compareAndSet(旧值,新值); 的返回结果

应用场景

1.原子计数器AtomicInteger
2.显式锁AbstractQueuedSynchronizer

他们的实现,都是跟我们的自定义工具类是一样的原理,就是核心两步

1.private Unsafe unsafe; //提供比较然后设置方法的功能
2.private volatile int oldValue; //保存旧值

比较,到底是在比较什么?到底是如何比较?

比较的到底又是哪些值?

本质是

1.自定义实现类.get旧值(); //这里的旧值,就是自定义类的数据
2.Unsafe.compareAndSet(旧值,新值); //这里的旧值,就是第一步读的数据

旧值分别是哪个,弄清楚了。现在的问题是,Unsafe.compareAndSet(旧值,新值);里的旧值,到底是在和谁比较?还是和自定义实现类的数据进行比较。

因为第一步,和第二步,是两个操作,所以这两个操作不是原子的,因此,Unsafe.compareAndSet(旧值,新值); 的返回值才会有true或false两种情况。

真正原子的地方,是Unsafe.compareAndSet(旧值,新值);这个方法本身。即包含了1.比较校验数据2.设置新的数据,这两步操作。

最佳实践

一般都是直接使用jdk提供的工具类,工具类的本质是封装了1.Unsafe //用于比较设置 2.数据 //用于同步。

除非jdk不能满足需求,才会自己去实现工具类。

本质

比较设置,本质是为了解决线程安全问题,

工具类

作用就是同步工具类。本质也是为了解决线程安全问题。

不管是谁实现的,你自己实现的,还是jdk实现的,作用和要解决的问题是一样的。