CAS自旋锁
手写自旋锁
public class SpinLockDemo { AtomicReference<Thread> atomicReference = new AtomicReference<>(); public void lock(){ Thread thread = Thread.currentThread(); System.out.println(thread.getName()+ " --- come in"); //while循环持续尝试拿锁,成功了才能跳出循环 while (!atomicReference.compareAndSet(null, thread)){ } } public void unlock(){ Thread thread = Thread.currentThread(); atomicReference.compareAndSet(thread,null); System.out.println(thread.getName()+ " --- task over, unlock"); } }
CAS的两大缺点
1,循环时间长,性能开销很大。
2,会导致"ABA"问题:CAS算法的一个重要前提需要取出内存中某时刻的数据并在当下时刻比较并替换,那么在这个时间差类会导致数据的变化
比如说一个线程1从内存位置V中取出A,这时候另一个线程2也从内存中取出A,并且线程2进行了一些数值操作变成了B,然后线程2又将V位置的数据变成A,这时候线程1进行CAS操作发现内存中仍然是A,预期OK,然后线程1操作成功。
尽管线程1的CAS操作成功,但是不代表这个过程就是没有问题的。
如何避免ABA问题?
使用AtomicStampedReference,也就是带有版本号的AtomicReference
//构造器:Book (类名) javabook (实例对象) 1 (版本号) AtomicStampedReference<Book> stampedReference = new AtomicStampedReference<>(javaBook, 1) //CAS方法:括号内依次为(预期对象,新对象,预期版本号,新版本号) boolean flag = stampedReference.compareAndSet(javaBook, mysqlBook, stampedReference.getStamp(), stampedReference.getStamp()+1)

浙公网安备 33010602011771号