实例讲解Java 自旋锁

所属分类: 软件编程 / java 阅读数: 197
收藏 0 赞 0 分享

  一直以来不是怎么清楚自旋锁,最近有点时间,好好的学习了一下;

  所谓的自旋锁在我的理解就是多个线程在尝试获取锁的时候,其中一个线程获取锁之后,其他的线程都处在一直尝试获取锁的状态,不会阻塞!!!那么什么叫做一直尝试获取锁呢?就是一个循环,比较经典的是AtomicInteger中的一个updateAndGet方法,下图所示(当然也可以直接看unsafe类中的getAndAddInt等类似方法);

  我们可以看出在while循环中使用CAS去尝试更新一个变量,如果更新失败,就会一直在这个循环中一直在尝试;成功的话,就可以到最后的return语句;

  由此我们可以大概知道如果自旋的线程过多,那么CPU的资源就会被大量消耗!!!

  顺便提一个东西叫做原子引用,官方提供了AtomicInteger,AtomicBoolean等原子类,那么如果我们自己定义的类也需要有原子性怎么办呢?所以官方提供了一个AtomicReference类,可以将我们自己定义的类封装一下,就成了我们自己的原子类,例如AtomicReference<Student> atomicReference = new AtomicReference<>();,然后我们对Student的实例进行CAS各种CAS操作;

  栗子:

package TestMain;


import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

@Slf4j
public class TestMain80 {
  //一个Thread类的原子引用
  AtomicReference<Thread> atomicReference = new AtomicReference<>();

  //加锁的方法
  public void myLock() {
    Thread currentThread = Thread.currentThread();
    log.info("myLock--Thread:{}", currentThread.getName());
    //这个就是自旋锁的核心,利用CAS比较当前原子引用中是否为null,如果是null,就把当前线程A放到里面去,
    // 此时线程B再到这里,那么就会CAS失败,一直在while循环中
    while (!atomicReference.compareAndSet(null, currentThread)) {

    }
  }

  //解锁的方法
  public void myUnlock() {
    Thread currentThread = Thread.currentThread();
    //CAS比较原子引用中是不是线程A,是的话就更新为null,此时在上面while中一直在自旋的线程B就可以跳出来了
    atomicReference.compareAndSet(currentThread, null);
    log.info("myUnlock--Thread:{}", currentThread.getName());
  }

  public static void main(String[] args) {
    TestMain80 testMain80 = new TestMain80();

    //线程A,首先加锁,然后等3秒中,然后释放锁
    new Thread(() -> {
      testMain80.myLock();
      try {
        TimeUnit.SECONDS.sleep(3);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
      testMain80.myUnlock();
    }, "A").start();

    //主线程等1秒,保证A线程先执行
    try {
      TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }

    //线程B,加锁再释放锁
    new Thread(() -> {
      testMain80.myLock();
      testMain80.myUnlock();
    }, "B").start();


  }
}

  上面的就是一个自旋锁的栗子,执行结果中首先是执行A线程的myLock方法,获取锁成功,之后的B线程虽然也会执行mylock方法,但是会在while循环中一直阻塞,直到线程A调用了myUnlock方法释放锁,最后两行才会打印出来;

以上就是实例讲解Java 自旋锁的详细内容,更多关于Java 自旋锁的资料请关注脚本之家其它相关文章!

更多精彩内容其他人还在看

Spring boot将配置属性注入到bean类中

本篇文章主要介绍了Spring boot将配置属性注入到bean类中,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

Java正则判断日期格式是否正确的方法示例

这篇文章主要介绍了Java正则判断日期格式是否正确的方法,结合实例形式分析了Java针对日期字符串正则判断的相关操作技巧,需要的朋友可以参考下
收藏 0 赞 0 分享

java Future 接口使用方法详解

这篇文章主要介绍了java Future 接口使用方法详解,Future接口是Java线程Future模式的实现,可以来进行异步计算的相关资料,需要的朋友可以参考下
收藏 0 赞 0 分享

Java 读取外部资源的方法详解及实例代码

这篇文章主要介绍了Java 读取外部资源的方法详解及实例代码的相关资料,经常有读取外部资源的要求,如配置文件等等需要读取,需要的朋友可以参考下
收藏 0 赞 0 分享

Java正则表达式之split()方法实例详解

这篇文章主要介绍了Java正则表达式之split()方法,结合实例形式较为详细的分析了split方法的功能、使用方法及相关注意事项,需要的朋友可以参考下
收藏 0 赞 0 分享

Java 存储模型和共享对象详解

这篇文章主要介绍了Java 存储模型和共享对象详解的相关资料,对Java存储模型,可见性和安全发布的问题是起源于Java的存储结构及共享对象安全,需要的朋友可以参考下
收藏 0 赞 0 分享

Java使用正则表达式实现找出数字功能示例

这篇文章主要介绍了Java使用正则表达式实现找出数字功能,结合实例形式分析了Java针对数字的匹配查找及非数字替换操作相关实现技巧,需要的朋友可以参考下
收藏 0 赞 0 分享

Spring核心IoC和AOP的理解

本文主要介绍了Spring核心IoC和AOP的相关知识。具有很好的参考价值,下面跟着小编一起来看下吧
收藏 0 赞 0 分享

详解Spring AOP 拦截器的基本实现

本篇文章主要介绍了详解Spring AOP 拦截器的基本实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
收藏 0 赞 0 分享

Mybatis 中的一对一,一对多,多对多的配置原则示例代码

这篇文章主要介绍了 Mybatis 中的一对一,一对多,多对多的配置原则示例代码,需要的朋友可以参考下
收藏 0 赞 0 分享
查看更多