• CAS 自旋锁(一)


    自旋锁

    持有锁的线程与等待竞争锁的线程不需要做内核态和用户态之间的切换进入阻塞状态,只需要循环等待持有锁的线程释放锁,从而避免了用户进程和内核切换的消耗

    非自旋锁里面,没有竞争到锁的线程需要进入阻塞状态,此时cpu切换状态使当前线程休眠,然后cpu切换线程执行其他操作任务,这个过程需要进行cpu上下文切换,很消耗cpu。

    因为自旋锁避免了操作系统进程调度和线程切换,所以自旋锁通常适用在时间比较短的情况

    什么是自旋

    “自旋”可以理解为“自我旋转”,这里的“旋转”指“循环”,比如 while 循环或者 for 循环。“自旋”就是自己在这里不停地循环,直到目标达成。而不像普通的锁那样,如果获取不到锁就进入阻塞

    自旋和非自旋的获取锁的流程

    自旋锁并不会放弃  CPU  时间片,而是通过自旋等待锁的释放,也就是说,它会不停地再次地尝试获取锁,如果失败就再次尝试,直到成功为止

    非自旋锁,如果它发现此时获取不到锁,它就把自己的线程切换状态,让线程休眠,然后 CPU 就可以在这段时间去做很多其他的事情,直到之前持有这把锁的线程释放了锁,于是 CPU 再把之前的线程恢复回来,让这个线程再去尝试获取这把锁。如果再次失败,就再次让线程休眠,如果成功,一样可以成功获取到同步资源的锁,这整个过程经常进行cpu上下文切换,很消耗CPU。
     

     非自旋锁和自旋锁最大的区别,就是如果它遇到拿不到锁的情况,它会把线程阻塞,直到被唤醒。而自旋锁会不停地尝试

    自旋锁的好处
    阻塞和唤醒线程都是需要高昂的开销的,如果同步代码块中的内容不复杂,那么可能转换线程带来的开销比实际业务代码执行的开销还要大!

    在很多场景下,可能我们的同步代码块的内容并不多,所以需要的执行时间也很短,如果我们仅仅为了这点时间就去切换线程状态,那么其实不如让线程不切换状态,而是让它自旋地尝试获取锁,等待其他线程释放锁,有时我只需要稍等一下,就可以避免上下文切换等开销,提高了效率!

    自旋锁的好处,那就是自旋锁用循环去不停地尝试获取锁,让线程始终处于 Runnable 状态,节省了线程状态切换带来的开销!
     

    自旋的缺点

    它最大的缺点就在于虽然避免了线程切换的开销,但是它在避免线程切换开销的同时也带来了新的开销,因为它需要不停得去尝试获取锁。如果这把锁一直不能被释放,那么这种尝试只是无用的尝试,会白白浪费处理器资源。也就是说,虽然一开始自旋锁的开销低于线程切换,但是随着时间的增加,这种开销也是水涨船高,后期甚至会超过线程切换的开销,得不偿失!

    适用场景

    自旋锁适用于并发度不是特别高的场景,以及临界区比较短小的情况,这样我们可以利用避免线程切换来提高效率

    可是如果临界区很大,线程一旦拿到锁,很久才会释放的话,那就不合适用自旋锁,因为自旋会一直占用 CPU 却无法拿到锁,白白消耗资源
     

  • 相关阅读:
    Phabricator Conduit API介绍
    责任链模式与spring容器的搭配应用
    BAT033:批量删除文件特定字符及特定字符之后的字符
    Matlab数字图像处理 01 图像数据的表示与基本运算
    【云开发】给我 10 分钟,带你上手一个 AWS serverless web server
    Spring5源码-监听器原理
    Langchain Chain - RouterChain 根据输入相关性进行路由的路由链
    js为什么是单线程?
    对象的序列化流ObjectOutputStream和对象的反序列化流ObjectInputStream
    《HarmonyOS开发 – OpenHarmony开发笔记(基于小型系统)》第6章 环境监测系统
  • 原文地址:https://blog.csdn.net/Jay112011/article/details/126763400