• 解决驱动开发中并发和竞争中的问题----------自旋锁


    什么是自旋锁

    是指临界区资源被持有锁线程A拥有的时候,别的线程B只能原地等待不会进入睡眠,直到A释放锁,那么A才可以访问临界区资源

    注意:自旋锁一般是用在等待时间比较短的地方,如果等待时间较长的话一般考虑使用信号量

    结构体:spinlock_t

    在这里插入图片描述

    相关API函数

    下面的API是不考虑中断情况下的
    在这里插入图片描述
    主要是下面两个函数

    获得锁函数 void spin_lock(spinlock_t *lock) 获取指定的自旋锁,也叫做加锁

    解锁函数 void spin_unlock(spinlock_t *lock) 释放指定的自旋锁

    注意:上面的自旋锁API函数适用于SMP或支持抢占的单CPU下线程之间的并发访问, 也就是用于线程与线程之间(不考虑中断),被自旋锁保护的临界区一定不能调用任何能够引起睡眠和阻塞的 API 函数,否则的话会可能会导致死锁现象的发生

    注意发生死锁:
    由于获得锁之后内核会自动禁止抢占,如果线程A进入睡眠的话就相当于放弃了CPU,那么此时B线程就会运行,此时B也想获得锁,但是线程A并没有释放掉锁,并且A由于禁止抢占式不能被唤醒,所以B只能在外面等待,所以就出现死锁

    考虑中断的情况
    如果线程之间来了个中断,又会是什么情况呢
    在这里插入图片描述
    线程 A 先运行,并且获取到了 lock 这个锁,当线程 A 运行程序的时候中断发生了,中断抢走了CPU 使用权。右边的中断服务函数也要获取 lock 这个锁, 但是这个锁被线程 A 占有着,中断就会一直自旋,等待锁有效。但是在中断服务函数执行完之前,线程 A 是不可能执行的,线程 A 说“你先放手”,中断说“你先放手”,场面就这么僵持着,死锁发生!

    最好的解决方法就是获取锁之前关闭本地中断

    即调用下面的函数获得锁即可
    在这里插入图片描述

    使用自旋锁一般步骤

    在这里插入图片描述
    在这里插入图片描述

    注意事项:

    在这里插入图片描述

    总结:
    1)自旋锁的使用可以在中断中,如果有中断的话必须使用考虑中断的API获得锁,不然会出现死锁,
    2)自旋锁必须是等待时间比较短,因为自旋锁会一直占用CPU,如果需要等待长时间即进入睡眠的话那就考虑信号量,下面一篇介绍信号量
    3)自旋锁不能使用睡眠或阻塞的相关函数

  • 相关阅读:
    C++调用Python(混合编程)函数整理总结
    C# 图解教程 第5版 —— 第5章 类的基本概念
    MySQL数据库——索引(6)-索引使用(覆盖索引与回表查询,前缀索引,单列索引与联合索引 )、索引设计原则、索引总结
    mac安装hive 2.3.9
    python的输入input()和输出print(),及经验用法
    生物素修饰肽:Biotin-NSDCIISRKIEQKE ,CAS: 2022956-39-2
    MySQL6
    范畴论(Category Theory)的基本介绍
    最新最全面的Spring详解(五)——事务管理
    NO1-Kafka如何通过网络接收/发送请求
  • 原文地址:https://blog.csdn.net/qq_24093081/article/details/127125709