实例讲解Java 自旋锁

 更新时间:2020年09月12日 14:11:10   作者:java小新人  
这篇文章主要介绍了Java 自旋锁的相关资料,帮助大家更好的理解和学习Java并发,感兴趣的朋友可以了解下

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

  所谓的自旋锁在我的理解就是多个线程在尝试获取锁的时候,其中一个线程获取锁之后,其他的线程都处在一直尝试获取锁的状态,不会阻塞!!!那么什么叫做一直尝试获取锁呢?就是一个循环,比较经典的是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 自旋锁的资料请关注脚本之家其它相关文章!

相关文章

  • java实现的冒泡排序算法示例

    java实现的冒泡排序算法示例

    这篇文章主要介绍了java实现的冒泡排序算法,结合实例形式分析了冒泡排序算法的具体操作步骤与实现技巧,需要的朋友可以参考下
    2017-01-01
  • springboot整合JPA访问Mysql的实现方法

    springboot整合JPA访问Mysql的实现方法

    本文主要介绍了springboot整合JPA访问Mysql的实现方法,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02
  • 使用Java的Spring框架编写第一个程序Hellow world

    使用Java的Spring框架编写第一个程序Hellow world

    这篇文章主要介绍了Java的Spring框架并用其开始编写第一个程序Hellow world的方法,Spring是Java的SSH三大web开发框架之一,需要的朋友可以参考下
    2015-12-12
  • java 枚举类中的valueOf用法说明

    java 枚举类中的valueOf用法说明

    这篇文章主要介绍了java 枚举类中的valueOf用法说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • Java如何解决发送Post请求报Stream closed问题

    Java如何解决发送Post请求报Stream closed问题

    这篇文章主要介绍了Java如何解决发送Post请求报Stream closed问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06
  • Java SpringBoot实现AOP

    Java SpringBoot实现AOP

    AOP包括连接点(JoinPoint)、切入点(Pointcut)、增强(Advisor)、切面(Aspect)、AOP代理(AOP Proxy),具体的方法和类型下面文章会举例说明,感兴趣的小伙伴和小编一起阅读全文吧
    2021-09-09
  • java中orElse和orElseGet方法区别小结

    java中orElse和orElseGet方法区别小结

    这篇文章主要给大家介绍了关于java中orElse和orElseGet方法区别的相关资料,两者之间的区别细微,但是却在某些场景下显的很重要,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2023-10-10
  • 详解Spring注解驱动开发之属性赋值

    详解Spring注解驱动开发之属性赋值

    今天带大家学习Spring注解驱动开发的相关知识,文中有非常详细的代码示例,对正在学习Java的小伙伴们很有帮助,需要的朋友可以参考下
    2021-05-05
  • java json不生成null或者空字符串属性(详解)

    java json不生成null或者空字符串属性(详解)

    下面小编就为大家带来一篇java json不生成null或者空字符串属性(详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-02-02
  • Spring boot整合jsp和tiles模板示例

    Spring boot整合jsp和tiles模板示例

    这篇文章主要介绍了Spring boot整合jsp模板和tiles模板的示例演示过程,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-03-03

最新评论