mutex 和spin lock的区别

在这里推荐一本书<深入Linux内核机制分析>,这本书对这些讲得非常好,对有基础的朋友帮助会很大,新手建议不好要使用,因为有一种云里雾里的感觉,非常的枯燥。

有哪些内核锁机制?

(1)原子操作

atomic_t数据类型,atomic_inc(atomic_t *v)将v加1

原子操作比普通操作效率要低,因此必要时才使用,且不能与普通操作混合使用

如果是单核处理器,则原子操作与普通操作相同

(2)自旋锁

spinlock_t数据类型,spin_lock(&lock)和spin_unlock(&lock)是加锁和解锁

等待解锁的进程将反复检查锁是否释放,而不会进入睡眠状态(忙等待),所以常用于短期保护某段代码

同时,持有自旋锁的进程也不允许睡眠,不然会造成死锁——因为睡眠可能造成持有锁的进程被重新调度,而再次申请自己已持有的锁

如果是单核处理器,则自旋锁定义为空操作,因为简单的关闭中断即可实现互斥

(3)信号量与互斥量

struct semaphore数据类型,down(struct semaphore * sem)和up(struct semaphore * sem)是占用和释放

struct mutex数据类型,mutex_lock(struct mutex *lock)和mutex_unlock(struct mutex *lock)是加锁和解锁

竞争信号量与互斥量时需要进行进程睡眠和唤醒,代价较高,所以不适于短期代码保护,适用于保护较长的临界区

1)互斥量用于线程的互斥,信号线用于线程的同步

这是互斥量和信号量的根本区别,也就是互斥和同步之间的区别

互斥:是指某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的

同步:是指在互斥的基础上(大多数情况),通过其它机制实现访问者对资源的有序访问。在大多数情况下,同步已经实现了互斥,特别是所有写入资源的情况必定是互斥的。少数情况是指可以允许多个访问者同时访问资源

(2)互斥量值只能为0/1,信号量值可以为非负整数

也就是说,一个互斥量只能用于一个资源的互斥访问,它不能实现多个资源的多线程互斥问题。信号量可以实现多个同类资源的多线程互斥和同步。当信号量为单值信号量是,也可以完成一个资源的互斥访问

(3)互斥量的加锁和解锁必须由同一线程分别对应使用,信号量可以由一个线程释放,另一个线程得到

信号量mutex是sleep-waiting。 就是说当没有获得mutex时,会有上下文切换,将自己、加到忙等待队列中,直到另外一个线程释放mutex并唤醒它,而这时CPU是空闲的,可以调度别的任务处理。

而自旋锁spin lock是busy-waiting。就是说当没有可用的锁时,就一直忙等待并不停的进行锁请求,直到得到这个锁为止。这个过程中cpu始终处于忙状态,不能做别的任务。

例如在一个双核的机器上有两个线程(线程A和线程B),它们分别运行在Core0 和Core1上。 用spin-lock,coer0上的线程就会始终占用CPU。
另外一个值得注意的细节是spin lock耗费了更多的user time。这就是因为两个线程分别运行在两个核上,大部分时间只有一个线程能拿到锁,所以另一个线程就一直在它运行的core上进行忙等待,CPU占用率一直是100%;而mutex则不同,当对锁的请求失败后上下文切换就会发生,这样就能空出一个核来进行别的运算任务了。(其实这种上下文切换对已经拿着锁的那个线程性能也是有影响的,因为当该线程释放该锁时它需要通知操作系统去唤醒那些被阻塞的线程,这也是额外的开销)

总结
(1)Mutex适合对锁操作非常频繁的场景,并且具有更好的适应性。尽管相比spin lock它会花费更多的开销(主要是上下文切换),但是它能适合实际开发中复杂的应用场景,在保证一定性能的前提下提供更大的灵活度。

(2)spin lock的lock/unlock性能更好(花费更少的cpu指令),但是它只适应用于临界区运行时间很短的场景。而在实际软件开发中,除非程序员对自己的程序的锁操作行为非常的了解,否则使用spin lock不是一个好主意(通常一个多线程程序中对锁的操作有数以万次,如果失败的锁操作(contended lock requests)过多的话就会浪费很多的时间进行空等待)。

(3)更保险的方法或许是先(保守的)使用 Mutex,然后如果对性能还有进一步的需求,可以尝试使用spin lock进行调优。毕竟我们的程序不像Linux kernel那样对性能需求那么高(Linux Kernel最常用的锁操作是spin lock和rw lock)。

时间: 2024-12-10 10:46:06

mutex 和spin lock的区别的相关文章

Spin lock 与mutex 的区别--2011.01.06

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

深层次探讨mutex与semaphore之间的区别

深层次探讨mutex与semaphore之间的区别 作者 digoal 日期 2016-11-10 标签 mutex , semaphore , Linux , 锁 , 内核 背景 本文依旧和<PostgreSQL 同步流复制锁瓶颈分析>这篇文章有关. 本文主要介绍一下Linux下面信号量(semaphore)和互斥锁(mutex)的区别. 原文地址 http://www.aichengxu.com/view/2456963 原文 看过Linux内核的同学都知道,Linux内核中除了有sema

Linux内核同步机制之(四):spin lock【转】

转自:http://www.wowotech.net/kernel_synchronization/spinlock.html 一.前言 在linux kernel的实现中,经常会遇到这样的场景:共享数据被中断上下文和进程上下文访问,该如何保护呢?如果只有进程上下文的访问,那么可以考虑使用semaphore或者mutex的锁机制,但是现在中断上下文也参和进来,那些可以导致睡眠的lock就不能使用了,这时候,可以考虑使用spin lock.本文主要介绍了linux kernel中的spin loc

spin lock的理解

为什么在spin lock保护的代码里面不允许有休眠的操作呢? 因为spin lock不是空实现的前提下(内核没关抢占,或者是SMP打开),spin lock中是关抢占的,如果一个进程A拿到锁,内核抢占暂时被关闭了,然后A休眠了,此时由调度算法切换到了进程B执行,进程B想要想要获得这个锁的时候发生了死锁,尽管进程B的时间片会被用完,但是由于内核抢占被禁止了,所以B不会被调度出去,这就形成了死锁. 如果A用 spin_lock_irqsave的方式,那么此时中断都是被禁止的,时钟中断计数不会更新了

深入Synchronized和java.util.concurrent.locks.Lock的区别详解_java

主要相同点:Lock能完成Synchronized所实现的所有功能.主要不同点:Lock有比Synchronized更精确的线程予以和更好的性能.Synchronized会自动释放锁,但是Lock一定要求程序员手工释放,并且必须在finally从句中释放.synchronized 修饰方法时 表示同一个对象在不同的线程中 表现为同步队列如果实例化不同的对象 那么synchronized就不会出现同步效果了.1.对象的锁 所有对象都自动含有单一的锁. JVM负责跟踪对象被加锁的次数.如果一个对象被

spin_lock &amp; mutex_lock的区别? 【转】

转自:http://www.cnblogs.com/bitter-first-sweet-last/p/4528633.html 转自:http://blog.csdn.net/sunnytina/article/details/7615520 为什么需要内核锁? 多核处理器下,会存在多个进程处于内核态的情况,而在内核态下,进程是可以访问所有内核数据的,因此要对共享数据进行保护,即互斥处理   有哪些内核锁机制? (1)原子操作 atomic_t数据类型,atomic_inc(atomic_t

C#中使用Monitor类、Lock和Mutex类来同步多线程的执行

转自 http://blog.csdn.net/tjvictor/archive/2007/01/20/1488290.aspx 在多线程中,为了使数据保持一致性必须要对数据或是访问数据的函数加锁,在数据库 中这是很常见的,但是在程序中由于大部分都是单线程的程序,所以没有加锁的必要,但是在多线程中,为了保持数据的同步,一定要加锁,好在 Framework中已经为我们提供了三个加锁的机制,分别是Monitor类.Lock关键字和Mutex类.         其中Lock关键词用法比较简单,Mon

boost库中thread多线程详解2——mutex与lock

1. mutex对象类 mutex类主要有两种:独占式与共享式的互斥量.▲ 独占式互斥量:mutex: 独占式的互斥量,是最简单最常用的一种互斥量类型try_mutex: 它是mutex的同义词,为了与兼容以前的版本而提供timed_mutex: 它也是独占式的互斥量,但提供超时锁定功能▲ 递归式互斥量:recursive_mutex: 递归式互斥量,可以多次锁定,相应地也要多次解锁recursive_try_mutex: 它是recursive_mutex 的同义词,为了与兼容以前的版本而提供

【锁】Latch、lock、 pin的区别

[锁]Latch.lock. pin的区别  我之前写过的几篇锁的文章: [锁]Oracle锁系列:http://blog.itpub.net/26736162/viewspace-2128896/[锁]Oracle死锁(DeadLock)的分类及其模拟:http://blog.itpub.net/26736162/viewspace-2127247/[故障处理]队列等待之TX - allocate ITL entry引起的死锁处理:http://blog.itpub.net/26736162/