在java中有很多地方都用到了CAS算法,如jdk1.8sycronized中轻量级锁就是CAS算法来实现的,ConcurrentHashMap在放弃分段锁后也是采用sycronized+cas来处理并发的读写请求,那为什么要用CAS算法呢。我的理解是因为CAS是一种无锁算法,抢锁过程不需要等待很久,可以尝试去修改一个共享变量,修改成功返回true,抢锁成功,否则返回false。这里要提一嘴java早期的sycronized实现原理,
是通过调用操作系统提供的方法去抢操作系统级的一个互斥量达到锁的效果,这里就意味着需要进行用户态到内核态的切换,高并发下性能可想而知。CAS不需要切换,可以绕过jvm直接去修改内存中的值,相对来说就非常高效了。
import com.zhouge.caozuo.model.UnSafeUtils; import org.springframework.stereotype.Component; import sun.misc.Unsafe; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.locks.LockSupport; @Component public class ZhougeLock { //一个共享变量,抢锁阶段通过修改status的值来抢锁 private volatile int status = 0; //status在内存中的偏移量,通过这个偏移量绕过jvm直接修改内存中status的值 private static long stateOffise; //Unsafe类,主要作用是可以绕过jvm直接修改内存中status的值 private static final Unsafe unsafe = UnSafeUtils.getUnSafe(); //记录当前获得锁的线程 private Thread lockHolder; //记录当前未获取锁的队列(无锁队列) private ConcurrentLinkedQueue<Thread> queue = new ConcurrentLinkedQueue<>(); //初始化的时候就确定该偏移量的位置,从而为后续CAS操作做铺垫 static { try{ stateOffise = unsafe.objectFieldOffset(ZhougeLock.class.getDeclaredField("status")); }catch (Exception e){ } } //尝试获取锁的方法 public boolean acquire(){ Thread thread = Thread.currentThread(); int state = getStatus(); //state = 0 ,说明没有线程持有锁 if(state == 0){ ConcurrentLinkedQueue<Thread> q = this.queue; //当无锁队列为空或者当前线程是队头元素且通过CAS操作将status由0改为1 if((q.size() == 0 || thread == queue.peek()) && compareAndSwap(0,1)){ //将当前锁的持有者设置为当前线程 setLockHolder(thread); //返回抢锁成功 return true; } } //抢锁失败 return false; } //线程获取锁的方法 public void lock(){ //抢锁成功直接返回 if(acquire()){ return; } //抢锁失败加入到无锁队列 Thread thread = Thread.currentThread(); queue.add(thread); //自旋的去抢锁 for(;;){ //队头抢到锁了 if(queue.peek() == thread && acquire()){ queue.poll(); return; } //为了减少cpu的消耗,将该线程阻塞住 LockSupport.park(); } } //释放锁的方法 public void unlock(){ Thread thread = Thread.currentThread(); //解铃还须系铃人 if(thread != getLockHolder()){ System.out.println("你跟我搞这个东西"); } int s = getStatus(); //解锁成功 if(compareAndSwap(1,0)){ setLockHolder(null); //弹出无锁队列中的第一个元素 Thread thread1 = queue.peek(); if(thread1 != null){ //唤醒该线程 LockSupport.unpark(thread1); } } } public boolean compareAndSwap(int start,int end){ return unsafe.compareAndSwapInt(this,stateOffise,start,end); } public Integer getStatus() { return status; } public void setStatus(Integer status) { this.status = status; } public static long getStateOffise() { return stateOffise; } public static Unsafe getUnsafe() { return unsafe; } public Thread getLockHolder() { return lockHolder; } public void setLockHolder(Thread lockHolder) { this.lockHolder = lockHolder; } public ConcurrentLinkedQueue<Thread> getQueue() { return queue; } public void setQueue(ConcurrentLinkedQueue<Thread> queue) { this.queue = queue; } }