Java中的自旋锁spinlock详解

 更新时间:2024年01月13日 10:12:46   作者:java架构师-太阳  
这篇文章主要介绍了Java中的自旋锁spinlock详解,自旋锁就是循环尝试获取锁,不会放弃CPU时间片,减伤cup上下文切换,缺点是循环会消耗cpu,需要的朋友可以参考下

自旋锁

过程

获取锁 访问共享资源 释放锁

自旋锁

循环尝试获取锁,不会放弃CPU时间片,减伤cup上下文切换,缺点是循环会消耗cpu

非自旋锁

如果获取不到锁,让线程休眠,CPU就可以在这段时间去做很多其他的事情,直到之前持有这把锁的线程释放了锁,于是CPU再把之前的线程恢复回来,让这个线程再去尝试获取这把锁。若再次失败,就再次让线程休眠,若成功,一样可以成功获取到同步资源的锁

在这里插入图片描述

如果在获取自旋锁时,没有任何执行单元保持该锁,那么将立即获取锁。 如果在获取锁时已经有持有者,那么锁操作将自旋,直到自旋锁的保持者释放了锁。

缺点

自旋锁一直占用着CPU,他在未获得锁的情况下,一直运行(自旋),所以占用着CPU,如果不能在很短的时间内获得锁,这无疑会使CPU效率降低

互斥锁与自旋锁区别

互斥锁  在未获得锁时,cup会进行切换,不会一直等待

自旋锁   在未获得锁时,一直占用着CPU,一直运行(自旋)抢占CUP

在多核机器中,如果锁住的“事务”很简单,占用很少时间,应该用自旋锁,自旋锁代价比互斥锁会小很多。

”事务”很快执行完毕,自旋的消耗远远小于陷入sleep和wake的消耗。如果锁住“事务”粒度较大,就应该使用互斥锁,因为如果用自旋锁,那么在“事务”执行过程中自旋很长时间还不如使得线程sleep

在单核机器中。自旋锁没有任何意义的,自旋锁只会浪费唯一核心的cpu 时间片,这个时刻没有任何线程会运行的。

所以单核机器中,不论锁住的”事务”的粒度大小都要使用。

手写自旋

public class SpinLockDemo {
    AtomicReference<Thread> atomicReference = new AtomicReference<>();
    public void lock() {
        Thread thread = Thread.currentThread();
        System.out.println(Thread.currentThread().getName()+"\t"+"----come in");
        // 因为atomicReference没有set,所以是null,compareAndSet方法比较如果是null,就修改为当前线程,如果不是null,就循环判断
        while (!atomicReference.compareAndSet(null, thread)) {
        }
    }
    public void unLock() {
        Thread thread = Thread.currentThread();
        // 如果atomicReference存储的是当前线程,就修改为null
        atomicReference.compareAndSet(thread,null);
        System.out.println(Thread.currentThread().getName()+"\t"+"----task over,unLock...");
    }
    public static void main(String[] args) {
        SpinLockDemo spinLockDemo = new SpinLockDemo();
        new Thread(() -> {
            spinLockDemo.lock();
            // 业务逻辑
            try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); }
            spinLockDemo.unLock();
        },"A").start();
        // 暂停500毫秒,线程A先于B启动
        try { TimeUnit.MILLISECONDS.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); }
        new Thread(() -> {
            spinLockDemo.lock();
            spinLockDemo.unLock();
        },"B").start();
    }
}

到此这篇关于Java中的自旋锁spinlock详解的文章就介绍到这了,更多相关自旋锁spinlock内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java实现简易学生管理系统

    Java实现简易学生管理系统

    这篇文章主要为大家详细介绍了Java实现简易学生管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-07-07
  • Java main方法String[]args原理实例解析

    Java main方法String[]args原理实例解析

    这篇文章主要介绍了Java main方法String[]args原理实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-06-06
  • 超详细的Java 问题排查工具单

    超详细的Java 问题排查工具单

    这篇文章主要介绍了超详细的Java 问题排查工具单,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-01-01
  • Spring Boot3 集成 Spring AI 实现 Advisor 增强机制的完整流程

    Spring Boot3 集成 Spring AI 实现 A

    Spring AI的Advisor API是一种声明式的拦截机制,借鉴了 Spring AOP 的设计理念,允许开发者在AI交互的生命周期关键节点插入自定义逻辑,本文全面介绍了Spring Boot集成Spring AI 1.0.0 实现 Advisor 增强机制的完整流程,感兴趣的朋友跟随小编一起看看吧
    2026-03-03
  • java使用HashMap实现斗地主(有序版)

    java使用HashMap实现斗地主(有序版)

    这篇文章主要为大家详细介绍了java使用ArrayList实现斗地主游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-03-03
  • Java中Stream API的使用示例详解

    Java中Stream API的使用示例详解

    Java 在 Java 8 中提供了一个新的附加包,称为 java.util.stream,该包由类、接口和枚举组成,允许对元素进行函数式操作, 本文主要介绍了Java中Stream API的具体使用,感兴趣的小伙伴可以了解下
    2023-11-11
  • 基于Java编写串口通信工具

    基于Java编写串口通信工具

    这篇文章主要为大家详细介绍了基于Java编写的一个带有图形界面的简单串口通信工具,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-12-12
  • 升级springboot中spring框架的版本的实现方法

    升级springboot中spring框架的版本的实现方法

    本文主要介绍了升级springboot中spring框架的版本的实现方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-08-08
  • IDEA使用maven创建hibernate项目的实现步骤(图文)

    IDEA使用maven创建hibernate项目的实现步骤(图文)

    本文主要介绍了IDEA使用maven创建hibernate项目的实现步骤,包括创建Maven项目,配置Hibernate,以及创建实体类映射到数据库等步骤,具有一定的参考价值,感兴趣的可以了解一下
    2023-08-08
  • SpringBoot整合JPA的实例代码

    SpringBoot整合JPA的实例代码

    本篇文章主要介绍了SpringBoot整合JPA的实例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-05-05

最新评论