自旋锁和互斥锁区别在哪_互斥锁的实现

自旋锁和互斥锁区别在哪_互斥锁的实现POSIXthreads(简称Pthreads)是在多核平台上进行并行编程的一套常用的API。线程同步(ThreadSynchronization)是并行编程中非常重要的通讯手段,其中最典型的应用就是用Pthreads提供的锁机制(lock)来对多个线程之间共享的临界区(CriticalSection)进行保护(另一种常用的同步机制是barrier)。Pthreads提供了多种锁机制:…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

POSIX threads(简称Pthreads)是在多核平台上进行并行编程的一套常用的API。线程同步(Thread Synchronization)是并行编程中非常重要的通讯手段,其中最典型的应用就是用Pthreads提供的锁机制(lock)来对多个线程之间共 享的临界区(Critical Section)进行保护(另一种常用的同步机制是barrier)。

Pthreads提供了多种锁机制:
(1) Mutex(互斥量):pthread_mutex_***
(2) Spin lock(自旋锁):pthread_spin_***
(3) Condition Variable(条件变量):pthread_con_***
(4) Read/Write lock(读写锁):pthread_rwlock_***

Pthreads提供的Mutex锁操作相关的API主要有:
pthread_mutex_lock (pthread_mutex_t *mutex);
pthread_mutex_trylock (pthread_mutex_t *mutex);
pthread_mutex_unlock (pthread_mutex_t *mutex);

Pthreads提供的与Spin Lock锁操作相关的API主要有:
pthread_spin_lock (pthread_spinlock_t *lock);
pthread_spin_trylock (pthread_spinlock_t *lock);
pthread_spin_unlock (pthread_spinlock_t *lock);

曾经有个经典的例子来比喻自旋锁:A,B两个人合租一套房子,共用一个厕所,那么这个厕所就是共享资源,且在任一时刻最多只能有一个人在使用。当厕所闲置时,谁来了都可以使用,当A使用时,就会关上厕所门,而B也要使用,但是急啊,就得在门外焦急地等待,急得团团转,是为“自旋”,呵呵。这个比喻还算恰当吧,大家也明白为什么要求锁的持有时间尽量短了吧!A B 相当于 cpu 内核,厕所就相当于互斥资源。

从 实现原理上来讲,Mutex属于sleep-waiting类型的锁。例如在一个双核的机器上有两个线程(线程A和线程B),它们分别运行在Core0和 Core1上。假设线程A想要通过pthread_mutex_lock操作去得到一个临界区的锁,而此时这个锁正被线程B所持有,那么线程A就会被阻塞 (blocking),Core0 会在此时进行上下文切换(Context Switch)将线程A置于等待队列中,此时Core0就可以运行其他的任务(例如另一个线程C)而不必进行忙等待。而Spin lock则不然,它属于busy-waiting类型的锁,如果线程A是使用pthread_spin_lock操作去请求锁,那么线程A就会一直在 Core0上进行忙等待并不停的进行锁请求,直到得到这个锁为止。自旋锁 本来就只是一个很简单的同步机制,在 SMP 之前根本就没这个东西,一切都是 Event 之类的同步机制,这类同步机制都有一个共性就是 一旦资源被占用都会产生任务切换,任务切换涉及很多东西的(保存原来的上下文,按调度算法选择新的任务,恢复新任务的上下文,还有就是要修改cr3寄存器会导致cache失效)这些都是需要大量时间的,因此用 Event 之类来同步一旦涉及到阻塞代价是十分昂贵的,比如 我用一个Event来控制2行代码的原子操作  这个时候一个CPU正在执行这个代码  另一个CPU也要进入  另一个CPU就会产生任务切换  为了短短的两行代码 就进行任务切换执行大量的代码  对系统性能不利 另一个CPU还不如直接有条件的死循环 等待那个CPU把那两行代码执行完

这也就是为什么自旋锁 要调整运行级别  因为另一个CPU可能在死循环不干活  自己必须快点执行完  要快点执行完  就必须保证自己的原子性  因此提高权限关闭中断是必须的

其实windows的自旋锁机制还是很简单的了  linux更复杂  linux提供了更多自旋锁操作方式 尤其是对中断中使用自旋锁的情况  当然一般是不提倡中断中使用自旋锁的 

 

所以,自旋锁一般用用多核的服务器。 

 

自旋锁(Spin lock)

自旋锁与互斥锁有点类似,只是自旋锁不会引起调用者睡眠,如果自旋锁已经被别的执行单元保持,调用者就一直循环在那里看是 否该自旋锁的保持者已经释放了锁,”自旋”一词就是因此而得名。其作用是为了解决某项资源的互斥使用。因为自旋锁不会引起调用者睡眠,所以自旋锁的效率远 高于互斥锁。虽然它的效率比互斥锁高,但是它也有些不足之处:
    1、自旋锁一直占用CPU,他在未获得锁的情况下,一直运行--自旋,所以占用着CPU,如果不能在很短的时 间内获得锁,这无疑会使CPU效率降低。
    2、在用自旋锁时有可能造成死锁,当递归调用时有可能造成死锁,调用有些其他函数也可能造成死锁,如 copy_to_user()、copy_from_user()、kmalloc()等。
因此我们要慎重使用自旋锁,自旋锁只有在内核可抢占式或SMP的情况下才真正需要,在单CPU且不可抢占式的内核下,自旋锁的操作为空操作。自旋锁适用于锁使用者保持锁时间比较短的情况下。
       自旋锁的用法如下:
   首先定义:spinlock_t x;
 然后初始化:spin_lock_init(spinlock_t *x);   //自旋锁在真正使用前必须先初始化
 在2.6.11内核中将定义和初始化合并为一个宏:DEFINE_SPINLOCK(x)
    
  获得自旋锁:spin_lock(x);   //只有在获得锁的情况下才返回,否则一直“自旋”
                           spin_trylock(x);  //如立即获得锁则返回真,否则立即返回假
      释放锁:spin_unlock(x);
    
结合以上有以下代码段:

    spinlock_t lock;        //定义一个自旋锁
    spin_lock_init(&lock);
    spin_lock(&lock);    
    …….        //临界区
    spin_unlock(&lock);   //释放锁
    
    还有一些其他用法:
spin_is_locked(x)
    //  该宏用于判断自旋锁x是否已经被某执行单元保持(即被锁),如果是,   返回真,否则返回假。
spin_unlock_wait(x)
    //  该宏用于等待自旋锁x变得没有被任何执行单元保持,如果没有任何执行单元保持该自旋锁,该宏立即返回,否
    //将循环    在那里,直到该自旋锁被保持者释放。

spin_lock_irqsave(lock, flags)
    //  该宏获得自旋锁的同时把标志寄存器的值保存到变量flags中并失效本地中//断。相当于:spin_lock()+local_irq_save()
spin_unlock_irqrestore(lock, flags)
    //  该宏释放自旋锁lock的同时,也恢复标志寄存器的值为变量flags保存的//值。它与spin_lock_irqsave配对使用。
    //相当于:spin_unlock()+local_irq_restore()

spin_lock_irq(lock)
     //该宏类似于spin_lock_irqsave,只是该宏不保存标志寄存器的值。相当         //于:spin_lock()+local_irq_disable()
spin_unlock_irq(lock)
    //该宏释放自旋锁lock的同时,也使能本地中断。它与spin_lock_irq配对应用。相当于: spin_unlock()+local_irq+enable()

spin_lock_bh(lock)
    //  该宏在得到自旋锁的同时失效本地软中断。相当于:  //spin_lock()+local_bh_disable()
spin_unlock_bh(lock)
      //该宏释放自旋锁lock的同时,也使能本地的软中断。它与spin_lock_bh配对//使用。相当于:spin_unlock()+local_bh_enable()

spin_trylock_irqsave(lock, flags)
    //该宏如果获得自旋锁lock,它也将保存标志寄存器的值到变量flags中,并且失//效本地中断,如果没有获得锁,它什么也不做。因此如果能够立即 获得锁,它等//同于spin_lock_irqsave,如果不能获得锁,它等同于spin_trylock。如果该宏//获得自旋锁lock,那需要 使用spin_unlock_irqrestore来释放。

spin_trylock_irq(lock)
    //该宏类似于spin_trylock_irqsave,只是该宏不保存标志寄存器。如果该宏获得自旋锁lock,需要使用spin_unlock_irq来释放。
spin_trylock_bh(lock)
    //  该宏如果获得了自旋锁,它也将失效本地软中断。如果得不到锁,它什么//也不做。因此,如果得到了锁,它等同于spin_lock_bh,如果得 不到锁,它等同//于spin_trylock。如果该宏得到了自旋锁,需要使用spin_unlock_bh来释放。
spin_can_lock(lock)
    //  该宏用于判断自旋锁lock是否能够被锁,它实际是spin_is_locked取反。//如果lock没有被锁,它返回真,否则,返回 假。该宏在2.6.11中第一次被定义,在//先前的内核中并没有该宏。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/200858.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • PLSQL详细使用教程及下载地址「建议收藏」

    PLSQL详细使用教程及下载地址「建议收藏」Oracle数据库连接必备,大公司玩转oracle数据库必备,虽然现在已经都用MYSQL替换了,但是不可否认这款软件的实力。中文版还具有语法加强、SQL和PL/SQL帮助、对象描述等功能特性。下载地址:http://kk04.cn/f-6339.html详细使用教程:http://kk04.cn/f-6342.html…

    2022年5月2日
    51
  • pycharm设置壁纸_pycharm界面开发

    pycharm设置壁纸_pycharm界面开发一:打开pycharm,按两次shift输入setbackgroundimage或者用快捷键Ctrl+shift+A二:选择setbackgroundimage进入如下界面第一处的箭头是背景图片的路径,第二个是透明度。选完图片之后点击ok就可以看到效果啦!三:最终效果ps:提升一下敲代码的big,哈哈!…

    2022年8月27日
    5
  • 一些常用单位之间的换算

    一些常用单位之间的换算一些常用单位之间的换算单位表格汇总单位表格汇总请注意下方的表格:目前只对链接(也就是文字颜色有变换的那个)产生了单位的换算,其他的没有做换算,如果有清楚的可以在本篇博文下留言,正确的留言单位换算就打算加上链接,错误的就请大家帮忙纠正一下,感谢各位配合!!!常用物理量的名称、符号和单位名称…

    2022年5月14日
    171
  • github下载文件很慢(github打开慢)

    方法:更改hosts文件第一步:查询ip地址使用https://www.ipaddress.com/查询下面3个网站的ip地址github.comgithub.global.ssl.fastly.netcodeload.github.com2020.8.21查询结果如下(请勿直接复制):140.82.112.4github.com199.232.69.194github.global.ssl.fastly.net140.82.113.10codeload.github.com第二步

    2022年4月16日
    47
  • 显性与隐性URL转发替代方案[通俗易懂]

    显性与隐性URL转发替代方案[通俗易懂]本文主要介绍了特殊情况下显性与隐性URL转发替代方案。

    2022年10月19日
    2
  • 数据库sql嵌套查询题_sql子查询嵌套优化

    数据库sql嵌套查询题_sql子查询嵌套优化一、嵌套查询概念在sql语言中,一个select-from-where语句成为一个查询块,将一个查询块嵌套在另一个查询块的where子句或having短语的条件中的查询成为嵌套查询。外层的查询块称为外层查询或父查询,内层的查询称为内层查询或子查询。注意点:子查询的select语句不能使用orderby子句,orderby只能对最终查询结果排序。嵌套查询分类:1、相关子查询/关联子查询:子查询的查询条件依赖于父查询,比如,如果子查询需要执行多次,即采用循环的方式,先从外部查询开始,每

    2022年8月10日
    6

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号