学习
实践
活动
工具
TVP
写文章

自旋

自旋:竞争的失败的线程,并不会真实的在操作系统层面挂起等待,而是JVM会让线程做 几个空循环(基于预测在不久的将来就能获得),在经过若干次循环后,如果可以获得,那么进入临界区,如果还不能获得, 适用场景:自旋可以减少线程的阻塞,这对于竞争不激烈,且占用时间非常短的代码块 来说,有较大的性能提升,因为自旋的消耗会小于线程阻塞挂起操作的消耗。 如果的竞争激烈,或者持有的线程需要长时间占用执行同步块,就不适合使用自旋 了,因为自旋锁在获取前一直都是占用cpu做无用功,线程自旋的消耗大于线程阻塞挂起操作的消耗,造成cpu的浪费。

31400

自旋

自旋的具体描述,可以看这里: https://blog.csdn.net/zy010101/article/details/83869140 自旋适合于被持有的时间比较短的场合,这样能避免线程调度的时候花费的成本 正如前面文章中所述,自旋一般作为底层的PV原语来实现其它类型的自旋锁在非抢占式调度中非常有用。 1.提供互斥机制 2.阻塞中断 阻塞中断,在非抢占式调度非常重要,中断处理程序不会使系统陷入死锁状态,因为它需要获取已被加锁的自旋。在这种内核,中断处理程序是不能休眠的,因为它只使用自旋。 (不抢占,只能等待时间片用完,或者是) 自旋锁在用户层面而言,不被经常使用。APUE这样写到自旋,从他的描述不难看出,不希望在用户层面使用自旋。 试图对没有加锁的自旋进行解锁,结果是未定义的;如果当前线程已经获取了自旋并加锁,继续加锁的结果也是未定义的。这有可能引起永久自旋

18820
  • 广告
    关闭

    热门业务场景教学

    个人网站、项目部署、开发环境、游戏服务器、图床、渲染训练等免费搭建教程,多款云服务器20元起。

  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    自旋

    在虚拟机为了解决这方面的性能损耗,通常情况下会对我们加的进行优化,目的就是提高程序的运行效率。优化主要分为5种,它们分别是:自旋消除、粗化、轻量级、偏向等。 在这一篇我们主要介绍第一种优化也就是自旋自旋 我们知道线程同步是用线程阻塞的方式来实现的。 所以为了解决上述问题,自旋一定有某种条件的限制,而不能让自旋一直等待下去。所以在虚拟机中有规定,自旋循环的次数默认是10次。 自旋本质上只有一种,但虚拟机为了更好的优化于是在JDK 1.6引入了自适应的自旋。自适应自旋的意思就是循环的次数不是上述所说的默认10次了。而是根据上一个线程获取到时它的自旋时间来决定的。 除此之外自适应自旋还会检测,如果发现对于某一个自旋完成后很少成功的获得,那么在以后要获取这个时将尽可能的省略掉自旋的过程,以避免浪费处理器的资源。

    62230

    自旋

    与互斥类似,自旋保证了公共数据在任意时刻最多只能由一条线程获取使用,不同的是在获取失败后自旋会采取自旋的处理方式。 自旋 自旋是指当一个线程尝试获取某个时,如果该已被其他线程占用,就一直循环检测是否被释放,而不是进入线程挂起或睡眠状态。一旦另外一个线程释放该后,此线程便能获得该自旋存在的问题 1、自旋一直占用CPU,在未获得的情况下,一直运行,如果不能在很短的时间内获得,会导致CPU效率降低。 2、试图递归地获得自旋会引起死锁。 递归程序决不能在持有自旋时调用它自己,也决不能在递归调用时试图获得相同的自旋。 由此可见,我们要慎重的使用自旋自旋适合于使用者保持时间比较短并且竞争不激烈的情况。 正是由于自旋使用者一般保持时间非常短,因此选择自旋而不是睡眠是非常必要的,自旋的效率远高于互斥

    17640

    Java面试题自旋

    自旋spinlock 重点:尝试获取的线程不会立即阻塞,而是采用循环的方式去尝试获取,这样的好处是减少线程上下文切换的消耗,不会堵塞。 this.compareAndSwapInt(var1, var2, var5, var5 + var4)); return var5; } 手敲自旋: 代码: package com.juc.lock; import java.util.Date; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference + new Date()); // 交换不成功则一直自旋 while (! Tue May 05 20:03:00 CST 2020 从结果可以看出,在线程1还没有释放时,线程2无法执行操作,仅仅是进入后不断循环直到线程1释放。 这就是自旋的妙处。

    35820

    Windows 驱动开发 - 自旋,队列自旋,链表自旋的使用.

    目录 windows 驱动开发之自旋结构的使用 一丶自旋 1.1 简介 1.2 使用自旋 1.3 错误的用法 二丶 链表中使用自旋 2.1 简介 三丶队列自旋 3.1 简介 windows 驱动开发之自旋结构的使用 其实自旋就是用来限制多线程对同一数据资源的访问而设定的。 而内核自旋与Ring3层的临界区类似。 看看如何使用自旋吧。 1.2 使用自旋 初始化自旋自旋是内核中提供的一种高IRQL的,用同步以独占的方式来访问某个资源。 既然我们使用自旋那么自然就不能是堆栈变量。 我们可以将 自旋锁定义为全局变量。 如果在堆栈那么相当于每次调用你的函数都初始化了一个自旋。 根本就起不到同步的 作用。 所以在使用队列自旋的时候一定注意不要和自旋混用。 比如等待使用 自旋, 释放使用队列自旋

    48610

    cas与自旋(轻量级就是自旋吗)

    CAS基于乐观思想来设计的,其不会引发阻塞,synchronize会导致阻塞。 原子类 java.util.concurrent.atomic包下的原子类都使用了CAS算法。 而java.util.concurrent的大多数类的实现都直接或间接的使用了这些原子类。 Unsafe类使Java拥有了类似C语言指针操作内存空间的能力,同时也带来了指针的安全问题。 注意:从1、2步可以看CAS机制实现的自旋,如果线程一直无法获取到,则一直自旋,不会阻塞 CAS和syncronized的比较 CAS线程不会阻塞,线程一致自旋 syncronized会阻塞线程 从Java1.5开始JUC包里提供了一个类AtomicStampedReference来解决ABA问题。 (2)循环时间长开销会比较大:自旋重试时间,会给CPU带来非常大的执行开销 (3)只能保证一个共享变量的原子操作,不能保证同时对多个变量的原子性操作 解决办法: 从Java1.5开始JDK提供了AtomicReference

    18310

    Java---偏向、轻量级自旋、重量级

    明确java线程切换的代价,是理解java各种的优缺点的基础之一。 基础知识之三:markword 在介绍java之前,先说下什么是markword,markword是java对象数据结构的一部分,要详细了解java对象的结构可以点击这里,这里只做markword的详细介绍 了解了markword结构,有助于后面了解java的加锁解锁过程; 小结 前面提到了java的4种,他们分别是重量级自旋、轻量级和偏向,  不同的有不同特点,每种只有在其特定的场景下 ,才会有出色的表现,java没有哪种能够在所有情况下都能有出色的效率,引入这么多的原因就是为了应对不同的情况; 前面讲到了重量级是悲观的一种,自旋、轻量级与偏向属于乐观,所以现在你就能够大致理解了他们的适用范围 ,但是具体如何使用这几种呢,就要看后面的具体分析他们的特性; java 自旋 自旋原理非常简单,如果持有的线程能在很短时间内释放资源,那么那些等待竞争的线程就不需要做内核态和用户态之间的切换进入阻塞挂起状态

    83230

    Java并发之高级自旋CLH和MCS

    myNode,L个有L个tail),CLH的一种变体被应用在了JAVA并发框架。 CLH在SMP系统结构下该法是非常有效的。 而MCS是在自己的结点的locked域上自旋等待。正因为如此,它解决了CLH在NUMA系统架构获取locked域状态内存过远的问题。 首先看CLH自旋的实现方式: package concurrent.spinlock; import java.util.concurrent.atomic.AtomicReference; /* 线程2 释放 线程3 获得 线程3 释放 MCS的实现方式: package concurrent.spinlock; import java.util.concurrent.atomic.AtomicReference ,AbstractQueuedSynchronizer是Java并发包的基石之一,而CLH的原理和思想则是AbstractQueuedSynchronizer的基石之一,JDK里面的CLH的是增强改进后的

    1.8K30

    Java 并发编程:AQS 的自旋

    互斥锁在AQS的互斥与共享已经做了详细介绍,一个一次只能由一个线程持有,其它线程则无法获得,除非已持有的线程释放了该。这里为什么提互斥呢? 与互斥类似,自旋保证了公共数据在任意时刻最多只能由一条线程获取使用,不同的是在获取失败后自旋会采取自旋的处理方式。 自旋 自旋是一种非阻塞,它的核心机制就在自旋两个字,即用自旋操作来替代阻塞操作。 自旋特点 自旋的核心机制就是死等,所有想要获得的线程都在不停尝试去获取,当然这也会引来竞争问题。 与互斥一样,自旋也只允许一个线程获得。 如此一来,没获得的线程也不会被挂起或阻塞,而是不断循环检查状态。 AQS的自旋机制 AQS框架不管是互斥还是共享实现的基础思想都是基于自旋的机制,不过它对自旋做了优化,这个后面会继续讲解。

    73960

    go 自旋

    自旋自旋是指当一个线程在获取的时候,如果已经被其他线程获取,那么该线程将循环等待,然后不断地判断是否能够被成功获取,直到获取到才会退出循环。 通过死循环检测的标志位, 避免了上下文切换的开销, 但是自旋会消耗CPU资源。自旋就主要用在临界区持时间非常短且CPU资源不紧张的情况下,自旋一般用于多核的服务器。 所以一般用于临界区持时间比较长的操作。 自旋实现基础版本go官方提供了atomic算法相关的包, 我们可以使用它直接实现一个自旋package mainimport ("runtime""sync""sync/atomic")type originSpinLock 21.54 ns/opBenchmarkSpinLockBenchmarkSpinLock-12 66324406 18.29 ns/op参考《go ants源码》《自旋

    21740

    Java并发编程:AQS的自旋

    互斥锁在AQS的互斥与共享已经做了详细介绍,一个一次只能由一个线程持有,其它线程则无法获得,除非已持有的线程释放了该。这里为什么提互斥呢? 与互斥类似,自旋保证了公共数据在任意时刻最多只能由一条线程获取使用,不同的是在获取失败后自旋会采取自旋的处理方式。 ? 01 自旋 自旋是一种非阻塞,它的核心机制就在自旋两个字,即用自旋操作来替代阻塞操作。 03 自旋特点 自旋的核心机制就是死等,所有想要获得的线程都在不停尝试去获取,当然这也会引来竞争问题。 与互斥一样,自旋也只允许一个线程获得。 05 AQS的自旋机制 AQS框架不管是互斥还是共享实现的基础思想都是基于自旋的机制,不过它对自旋做了优化,这个后面会继续讲解。

    23840

    liunx内核的互斥自旋和读写自旋的实现详解

    ); /* * Your basic SMP spinlocks, allowing only a single CPU anywhere */ typedef struct { //自旋为无符号的整型变量 * 简单的自旋操作。有两种变体,一种清除本地处理器上的IRQ,另一种不清除。 * * We make no fairness assumptions. They have a cost. 它们是有代价的 */ //判断自旋是否被锁定 先通过取地址拿到spinlock里的lock 再转为字符,再解引用判断是否小于0 #define spin_is_locked(x) (*(volatile signed char *)(&(x)->lock) <= 0) //等待自旋释放,barrier()保证禁止编译器任意排序 #define spin_unlock_wait(x) do { barrier (); } while(spin_is_locked(x)) //获取自旋内联汇编代码,这里只是code部分,剩下在用的时候肯定是有输出数和输入数的 #define spin_lock_string

    11030

    【说站】java如何实现可重入的自旋

    java如何实现可重入的自旋 说明 1、是指试图获得的线程不会堵塞,而是通过循环获得。 2、优点:减少上下文切换的消耗。 缺点:循环消耗CPU。 Runnable runnable = () -> {             System.out.println(Thread.currentThread().getName() + "开始尝试获取自旋 spinLock.lock();             try {                 System.out.println(Thread.currentThread().getName() + "获取到了自旋                 spinLock.unLock();                 System.out.println(Thread.currentThread().getName() + "释放了了自旋 实现可重入自旋的方法,希望对大家有所帮助。

    7830

    自旋是什么?

    自旋:竞争的失败的线程,并不会真实的在操作系统层面挂起等待,而是JVM会让线程做几个空循环(基于预测在不久的将来就能获得),在经过若干次循环后,如果可以获得,那么进入临界区,如果还不能获得,才会真实的将线程在操作系统层面进行挂起 适用场景:自旋可以减少线程的阻塞,这对于竞争不激烈,且占用时间非常短的代码块来说,有较大的性能提升,因为自旋的消耗会小于线程阻塞挂起操作的消耗。 如果的竞争激烈,或者持有的线程需要长时间占用执行同步块,就不适合使用自旋了,因为自旋锁在获取前一直都是占用cpu做无用功,线程自旋的消耗大于线程阻塞挂起操作的消耗,造成cpu的浪费。

    11610

    偏向、轻量级、重量级自旋、自适应自旋

    偏向 偏向就是在运行过程,对象的偏向某个线程。 1.1 偏向获取过程 查看Mark Word偏向的标识以及标志位,若是否为偏向为1,并且标志位为01,则该为可偏向状态。 复制对象头中的Mark Word到记录。 缺点:在线程竞争激烈,或持有的线程需要长时间执行同步代码块的情况下,使用自旋会使得CPU做太多无用功。 JDK1.6,设置参数-XX:+UseSpinning开启。 自适应自旋 自适应意味着自旋的时间不再固定了,而是由前一次在同一个锁上的自旋时间及的拥有者的状态来决定: 如果在同一个对象上,自旋等待之前成功获得过的,并且持有的线程正在运行,那么虚拟机就会认为这次自旋也很有可能再次成功

    84710

    多线程系统(四)-谈谈自旋

    优点:完美解决内核的缺点。            缺点:长时间一直循环会导致cpu的白白浪费,高并发竞争下、CPU的消耗特别严重。 混合:内核+自旋。  混合是先自旋一段时间或自旋多少次,再转成内核。            优点:内核自旋的折中方案,利用前二者优点,避免出现极端情况(自旋时间过长,内核时间过短)。             自旋示例 来看下我们自己简单实现的自旋:       int signal = 0; var li = new List<int>(); Parallel.For 从源码可以学到不少编程技巧,比如可以借鉴自旋+Thread.Yeild() 或 while+Thread.Yeild()等组合使用方式。  总结 本章介绍了自旋的基础及楼主的经验。 测试了下SpinLock和自己实现的自旋性能对比(并行添加1000w List<int>()),SpinLock是单纯的自旋性能2倍以上。

    66670

    Java 15种的介绍:公平,可重入,独享,互斥,乐观,分段自旋等等

    读写有三种状态:读加锁状态、写加锁状态和不加锁状态 读写锁在Java的具体实现就是ReadWriteLock 一次只有一个线程可以占有写模式的读写,但是多个线程可以同时占有读模式的读写。 传统的关系型数据库里边就用到了很多这种机制,比如行,表等,读,写等,都是在做操作之前先上锁。Javasynchronized和ReentrantLock等独占就是悲观思想的实现。 在Javajava.util.concurrent.atomic包下面的原子变量类就是使用了乐观的一种实现方式CAS实现的。 重量级会让其他申请的线程进入阻塞,性能降低。 自旋 我们知道CAS算法是乐观的一种实现方式,CAS算法又涉及到自旋,所以这里给大家讲一下什么是自旋。 但是自旋不会引起调用者睡眠,如果自旋已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋的保持者已经释放了,”自旋”一词就是因此而得名。 Java如何实现自旋

    32720

    CAS(cas自旋原理)

    java.util.concurrent包借助CAS实现了区别于synchronouse同步的一种乐观。 本文先从CAS的应用说起,再深入原理解析。 把写缓冲区的所有数据刷新到内存。 备注知识: 关于CPU的有如下3种:   3.1 处理器自动保证基本内存操作的原子性   首先处理器会自动保证基本的内存操作的原子性。 频繁使用的内存会缓存在处理器的L1,L2和L3高速缓存里,那么原子操作就可以直接在处理器内部缓存中进行,并不需要声明总线,在奔腾6和最近的处理器可以使用“缓存锁定”的方式来实现复杂的原子性。 自旋CAS如果长时间不成功,会给CPU带来非常大的执行开销。 AQS,非阻塞数据结构和原子变量类(java.util.concurrent.atomic包的类),这些concurrent包的基础类都是使用这种模式来实现的,而concurrent包的高层类又是依赖于这些基础类来实现的

    14310

    Java 15种的介绍:公平,可重入,独享,互斥,乐观,分段自旋等等

    读写有三种状态:读加锁状态、写加锁状态和不加锁状态 读写锁在Java的具体实现就是ReadWriteLock 一次只有一个线程可以占有写模式的读写,但是多个线程可以同时占有读模式的读写。 传统的关系型数据库里边就用到了很多这种机制,比如行,表等,读,写等,都是在做操作之前先上锁。Javasynchronized和ReentrantLock等独占就是悲观思想的实现。 在Javajava.util.concurrent.atomic包下面的原子变量类就是使用了乐观的一种实现方式CAS实现的。 重量级会让其他申请的线程进入阻塞,性能降低。 自旋 我们知道CAS算法是乐观的一种实现方式,CAS算法又涉及到自旋,所以这里给大家讲一下什么是自旋。 但是自旋不会引起调用者睡眠,如果自旋已经被别的执行单元保持,调用者就一直循环在那里看是否该自旋的保持者已经释放了,”自旋”一词就是因此而得名。 Java如何实现自旋

    15400

    扫码关注腾讯云开发者

    领取腾讯云代金券