实例讲解Java 自旋锁

作者:java小新人 时间:2021-09-17 09:38:50 

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

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

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

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

实例讲解Java 自旋锁

顺便提一个东西叫做原子引用,官方提供了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();

}
}

实例讲解Java 自旋锁

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

来源:https://www.cnblogs.com/wyq1995/p/12539853.html

标签:Java,自旋锁
0
投稿

猜你喜欢

  • Java编程中的检查型异常与非检查型异常分析

    2023-11-04 13:08:38
  • IDEA Error:java:无效的源发行版:13的解决过程

    2023-11-25 10:07:19
  • 深入理解java自旋锁

    2023-10-28 00:32:49
  • Mybatis注解增删改查的实例代码

    2022-03-31 01:26:15
  • java实现快速排序图文详解

    2022-10-11 16:35:18
  • 利用Spring boot如何创建简单的web交互应用

    2023-07-15 12:47:00
  • 详解Java注解的实现与使用方法

    2023-10-31 12:33:20
  • Java递归寻路实现,你真的理解了吗

    2022-09-17 02:24:34
  • 图解Java线程的生命周期

    2022-04-12 15:16:10
  • Java日志框架之logback使用详解

    2022-02-18 05:33:47
  • 深入XPath的详解以及Java示例代码分析

    2021-11-01 13:42:33
  • SpringBoot2整合Ehcache组件实现轻量级缓存管理

    2022-06-18 18:11:16
  • java.lang.NoClassDefFoundError错误解决办法

    2021-12-29 03:52:27
  • SpringBoot 项目瘦身maven/gradle详解

    2021-10-26 04:39:12
  • Mybatis延迟加载和缓存深入讲解

    2022-06-02 15:50:43
  • maven依赖版本没有按照最短路径原则生效的解决方案

    2023-04-04 20:49:09
  • java实现LRU缓存淘汰算法的方法

    2022-10-09 00:09:05
  • Springcloud-nacos实现配置和注册中心的方法

    2023-06-15 13:46:42
  • Java 单例模式的实现资料整理

    2022-05-29 21:27:33
  • Spring创建Bean的6种方式详解

    2022-07-18 19:10:13
  • asp之家 软件编程 m.aspxhome.com