Demo说明什么是自旋锁

概述

在程序开发中比较常见,所有的线程去争抢一个共同的资源时,为了避免出现超买超卖等并发问题,此时需要对其进行加锁解锁操作。

自旋锁在Java源码中和各种框架中都广泛使用,其本质就是一个死循环。让一个线程在这个循环中不断的循环,不继续向下执行其他代码,这种现象用比较文艺的词描述就是自旋

当通过CAS算法执行失败时,则一直死循环等待何时可以获取到锁。
当前一个线程释放锁成功后,后面的线程CAS算法比较和交换操作执行成功后,方可跳出循环。

如Java中sun.misc.Unsafe#getAndAddInt的源码部分一样:
在这里插入图片描述

手写一个自旋锁

接下来自己手写一个自旋锁,实现高并发环境下对数据操作的可控性。

package spin;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.atomic.AtomicReference;

/**
 * 手写 “自旋锁”;使用CAS算法
 */
@Slf4j
public class SpinLockDo {

    // 针对线程进行加锁
    AtomicReference<Thread> atomicReference = new AtomicReference();

    // 加锁操作
    public void myLock(){
        Thread thread = Thread.currentThread();
        log.info(thread.getName()+"-->myLock");
        // 模拟自旋
        // 1、当thread初始为null时,才能设置成功返回true
        // 2、当thread不是初始状态,则一直让其自旋
        while (!atomicReference.compareAndSet(null,thread)){
            // 1s打印一次
            TimeUnit.SECONDS.sleep(1);
            log.info(thread.getName()+"---自旋中....");
        }
    }

    // 解锁操作、
    public void myUnLock(){
        Thread thread = Thread.currentThread();
        log.info(thread.getName()+"-->myUnLock");
        // 使用CAS,当thread不是初始,则将其设置为初始化的null状态值
        atomicReference.compareAndSet(thread,null);
    }
}

测试自旋锁

package spin;

import java.util.concurrent.TimeUnit;

public class SpinLockDemo {
    public static void main(String[] args) throws InterruptedException {
        SpinLockDo spinLockDo = new SpinLockDo();
        new Thread(()->{
            try {
                spinLockDo.myLock();
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                spinLockDo.myUnLock();
            }
        },"t1").start();

        // 延迟2s
        TimeUnit.SECONDS.sleep(2);

        new Thread(()->{
            try {
                spinLockDo.myLock();
                TimeUnit.SECONDS.sleep(2);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                spinLockDo.myUnLock();
            }
        },"t2").start();
    }
}

执行后的结果

在这里插入图片描述
从结果中可以看出:

1、线程t1和t2都能进入自定义自旋锁工具类中。
2、线程t1先执行,拿到锁后,使用CAS变更了对象的值;使得线程t2在CAS计算中一直为false,由于取反则自旋。
3、当线程t1执行释放锁操作后,线程t2采取CAS算法获取到锁,结束自旋。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值