Java中的自旋锁与阻塞锁详解

 更新时间:2023年10月13日 10:37:28   作者:ゞ浪人与酒丶0  
这篇文章主要介绍了Java中的自旋锁与阻塞锁详解,阻塞锁是指当线程尝试获取锁失败时,线程进入阻塞状态,直到接收信号后被唤醒,阻塞或者唤醒一个Java线程需要操作系统切换CPU 状态来完成,这种状态转换 需要耗费处理器时间,需要的朋友可以参考下

自旋锁

阻塞或者唤醒一个Java线程需要操作系统切换CPU 状态来完成,这种状态转换 需要耗费处理器时间 如果同步代码块到代码过于简单,状态转换到时间有kennel比用户执行代码到时间还长 在许多场景下,同步资源到锁定时间短,为了这小段时间切换线程,线程的挂起和恢复可能会让系统得不偿失,

这里是为了当前线程“ 稍等一下”, 我们需要让当前线程进行自旋 ,如果自旋完成后前面锁定同步资源的线程以及释放了锁,那么当前线程就没必要阻塞,而是直接获取同步资源,从而避免线程的开销 阻塞锁和自旋锁相反,阻塞锁如果没有拿到锁,就会直接阻塞,知道被唤醒

阻塞锁

阻塞锁是指当线程尝试获取锁失败时,线程进入阻塞状态,直到接收信号后被唤醒.(线程的状态包括新建、就绪、运行、阻塞及死亡)在JAVA中,能够唤醒阻塞线程的操作包括Object.notify, Object.notifyAll, Condition.signal, LockSupport.unpark(JUC中引入)

原理和源码分析

在 jdk 1.5 及以上并发框架 Java.util.concurrent 的 atomic 下 都是自旋锁实现的

AtomicInteger 的实现 :自旋锁实现原理是CAS AtomicInteger 中是调用底层unsafe 进行自增操作的源码中的 do-while 循环就是一个自旋操作,如果修改过程中一踏线程竞争导致修改失败,就在while 死循环,直至成功

package com.dimple.test;
/**
 * 本实例演示下线程的自旋锁的实现
 */
public class SpinLockDemo {
    private static AtomicReference<Thread> atomicReference=new AtomicReference<>();
    public void lock(){
        Thread thread=Thread.currentThread();
        while(!atomicReference.compareAndSet(null,thread)){
            System.out.println(thread.getName()+"自旋锁获取失败,重新获取中");
        }
    }
    public void unlock(){
        Thread thread=Thread.currentThread();
        atomicReference.compareAndSet(thread,null);
    }
    public static void main(String[] args) {
        SpinLockDemo spinLockDemo=new SpinLockDemo();
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName()+"尝试获取自旋锁");
            spinLockDemo.lock();
            System.out.println(Thread.currentThread().getName()+"获取自旋锁成功");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            spinLockDemo.unlock();
            System.out.println(Thread.currentThread().getName()+"释放自旋锁");
        }).start();
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName()+"尝试获取自旋锁");
            spinLockDemo.lock();
            System.out.println(Thread.currentThread().getName()+"获取自旋锁成功");
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            spinLockDemo.unlock();
            System.out.println(Thread.currentThread().getName()+"释放自旋锁");
        }).start();
    }
}

Thread-0尝试获取自旋锁
Thread-0获取自旋锁成功
Thread-1尝试获取自旋锁
Thread-1自旋锁获取失败,重新获取中
Thread-1自旋锁获取失败,重新获取中
Thread-1自旋锁获取失败,重新获取中
Thread-1自旋锁获取失败,重新获取中

我们打开 AtomicInteger 源码看一下,这里是个 do while 循环

在这里插入图片描述

自旋锁的应用场景

自旋锁一般用于多核服务器,在并发度不是特别搞的情况下,比阻塞锁效率高

另外,自旋锁适用于临界区较小的情况,否则如果临界区很大,(线程一旦拿到锁,很多之后才会释放),那也是不适合的

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

相关文章

  • 基于JavaMail API收发邮件的方法

    基于JavaMail API收发邮件的方法

    这篇文章主要介绍了基于JavaMail API收发邮件的方法,实例分析了javamail的使用方法与相关注意事项,非常具有实用价值,需要的朋友可以参考下
    2015-07-07
  • Spring Boot 基于 CAS 实现单点登录的原理、实践与优化全解析(最新整理)

    Spring Boot 基于 CAS 实现单点登录的原理、实践与优化全解析(最新整理)

    本文详解SpringBoot集成CAS单点登录的原理、实现步骤及优缺点,涵盖CASServer与Client架构、票据机制、配置方法,并提供优化策略如集群部署、缓存加速和用户体验提升方案,助力企业实现统一认证与高效管理,感兴趣的朋友一起看看吧
    2025-07-07
  • Java servlet 使用 PrintWriter 时的编码与乱码的示例代码

    Java servlet 使用 PrintWriter 时的编码与乱码的示例代码

    本篇文章主要介绍了Java servlet 使用 PrintWriter 时的编码与乱码的示例代码,探讨了 PrintWriter 的缺省编码与普通字符流的缺省编码的差异,具有一定的参考价值,有兴趣的可以了解一下
    2017-11-11
  • Java mybatis常见问题及解决方案

    Java mybatis常见问题及解决方案

    这篇文章主要介绍了Java mybatis常见问题及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08
  • SpringCloud Hystrix 断路器的实现

    SpringCloud Hystrix 断路器的实现

    本文主要介绍了SpringCloud Hystrix 断路器的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-03-03
  • SpringBoot集成redisson实现延时队列教程

    SpringBoot集成redisson实现延时队列教程

    文章介绍了使用Redisson实现延迟队列的完整步骤,包括依赖导入、Redis配置、工具类封装、业务枚举定义、执行器实现、Bean创建、消费线程启动及测试接口验证,适用于需定时处理任务的场景
    2025-08-08
  • Java 实战范例之进销存管理系统的实现

    Java 实战范例之进销存管理系统的实现

    读万卷书不如行万里路,只学书上的理论是远远不够的,只有在实战中才能获得能力的提升,本篇文章手把手带你用java+vue+Springboot+ssm+mysql+maven+redis实现一个前后端分离的进销存管理系统,大家可以在过程中查缺补漏,提升水平
    2021-11-11
  • Matplotlib可视化之自定义颜色绘制精美统计图

    Matplotlib可视化之自定义颜色绘制精美统计图

    matplotlib提供的所有绘图都带有默认样式.虽然这可以进行快速绘图,但有时可能需要自定义绘图的颜色和样式,以对绘制更加精美、符合审美要求的图像.matplotlib的设计考虑到了此需求灵活性,很容易调整matplotlib图形的样式,需要的朋友可以参考下
    2021-06-06
  • SpringMVC使用注解实现登录功能

    SpringMVC使用注解实现登录功能

    这篇文章主要为大家详细介绍了SpringMVC使用注解实现登录功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-09-09
  • 听说用了YYYY-MM-dd的程序员,前些天都在加班改Bug

    听说用了YYYY-MM-dd的程序员,前些天都在加班改Bug

    这篇文章主要介绍了YYYY-MM-dd的实用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-01-01

最新评论