自旋锁

208 阅读2分钟

这是我参与8月更文挑战的第15天,活动详情查看:8月更文挑战

ps:昨天又是一样的七夕,呜呜呜~~~,大家呢?

mmexport1628864917714.jpg 学习学习!!!

介绍

  • 一种有名的无锁算法,不使用锁的情况下实现多线程间变量的同步

  • 尝试获取锁的线程不会立即阻塞,而是反复尝试的去获得锁,好处是减少上下文切换的消耗,缺点是消耗cpu

  • 是一种基于CAS的锁,此时比较并交换的类型变成了线程(Thread)

先来到该方法下,这就是一个自旋锁的实现思想

AtomicInteger - > getAndIncrement -> unsafe.getAndAddInt

public final int getAndAddInt(Object var1, long var2, int var4) {
    int var5;
    do {
        var5 = this.getIntVolatile(var1, var2);
    } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));

    return var5;

自旋锁Demo

1.使用了AtomicReference类实现原子引用线程,这里我们可以把AtomicReference当成一个容器,丢进这个容器的类型就可以实现原子操作,例如这边是Thread类型可以实现原子操作

2.刚开始的时候atomicReference没有Thread类型的数据,所以为null,那么在上锁的时候判断

while(!atomicReference.compareAndSet(null,curThread)){ }

此时期望值为null实际值为空,那么实际值就被修改为curThread(当前线程),获取锁成功,而BBB线在获取锁的时候期望值为空实际值却是AAA线程,暂时无法获得锁,就一直在while中循环尝试,直到AAA线程释放锁

3.unlock方法会比较是否为当前线程,如果是当前线程的话就释放锁(就是把atomicReference中的thread变成空,这样其他线程就能获取锁了)

public class SpinLockDemo {
    //原子引用线程
    AtomicReference<Thread> atomicReference = new AtomicReference<>();
    public static void main(String[] args) throws InterruptedException {
        SpinLockDemo spinLockDemo = new SpinLockDemo();
        new Thread(()->{
              spinLockDemo.myLock();
            try { Thread.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
            spinLockDemo.unlock();
          },"AAA").start();
        TimeUnit.SECONDS.sleep(1);//为了让A线程先获得cpu的时间片
        new Thread(()->{
            spinLockDemo.myLock();
            spinLockDemo.unlock();
        },"BBB").start();
    }
    public void myLock(){
        Thread curThread = Thread.currentThread();
        System.out.println(curThread.getName()+"\t com in ~~~");
        while(!atomicReference.compareAndSet(null,curThread)){

        }
    }
    public void unlock(){
        Thread curThread = new Thread().currentThread();

        atomicReference.compareAndSet(curThread,null);
        System.out.println(curThread.getName()+"\t 线程释放锁  ~~~");
    }
}

运行结果:

AAA	 com in ~~~
AAA	 线程释放锁  ~~~
BBB	 com in ~~~
BBB	 线程释放锁  ~~~