信号量、互斥体和自旋锁的区别

本文详细介绍了信号量和自旋锁的概念及其应用场景。包括它们在进程保持时间、使用场合、内核抢占等方面的差异,并解释了信号量与互斥锁的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

[cpp] view plaincopyprint?

            信号量/互斥体允许进程睡眠属于睡眠锁,自旋锁则不允许调用者睡眠,而是让其循环等待,所以有以下区别应用   
      
        1)、信号量和读写信号量适合于保持时间较长的情况,它们会导致调用者睡眠,因而自旋锁适合于保持时间非常短的情况  
        2)、自旋锁可以用于中断,不能用于进程上下文(会引起死锁)。而信号量不允许使用在中断中,而可以用于进程上下文  
        3)、自旋锁保持期间是抢占失效的,自旋锁被持有时,内核不能被抢占,而信号量和读写信号量保持期间是可以被抢占的  
         
    另外需要注意的是  
         1)、信号量锁保护的临界区可包含可能引起阻塞的代码,而自旋锁则绝对要避免用来保护包含这样代码的临界区,因为阻塞意味             着要进行进程的切换,如果进程被切换出去后,另一进程企图获取本自旋锁,死锁就会发生。  
         2)、在你占用信号量的同时不能占用自旋锁,因为在你等待信号量时可能会睡眠,而在持有自旋锁时是不允许睡眠的。  
      
      
      
    信号量和互斥体之间的区别  
      
       
      
    概念上的区别:       
      
          信号量:是进程间(线程间)同步用的,一个进程(线程)完成了某一个动作就通过信号量告诉别的进程(线程),别的进程(线程)再进行某些动作。有二值和多值信号量之分。  
      
         互斥锁:是线程间互斥用的,一个线程占用了某一个共享资源,那么别的线程就无法访问,直到这个线程离开,其他的线程才开始可以使用这个共享资源。可以把互斥锁看成二值信号量。    
      
      
      
    上锁时:  
      
         信号量: 只要信号量的value大于0,其他线程就可以sem_wait成功,成功后信号量的value减一。若value值不大于0,则sem_wait阻塞,直到sem_post释放后value值加一。一句话,信号量的value>=0。  
      
         互斥锁: 只要被锁住,其他任何线程都不可以访问被保护的资源。如果没有锁,获得资源成功,否则进行阻塞等待资源可用。一句话,线程互斥锁的vlaue可以为负数。    
      
       
      
    使用场所:  
      
         信号量主要适用于进程间通信,当然,也可用于线程间通信。而互斥锁只能用于线程间通信。  



FROM :  http://blog.youkuaiyun.com/zzhere2007/article/details/9106831


### 互斥锁、自旋锁信号量的概念及使用场景 #### 概念定义 - **互斥锁 (Mutex)** 是一种用于保护共享资源的机制,确保同一时刻只有一个线程能够访问该资源。它通过加锁解锁的操作来控制对临界区的访问[^3]。 - **自旋锁 (Spin Lock)** 是一种轻量级的锁,在尝试获取锁的过程中会不断循环检查直到锁可用为止。这种行为称为“忙等待”,适用于短时间持有锁的情况[^1]。 - **信号量 (Semaphore)** 提供了一种更灵活的方式管理多个资源的访问权限。它可以表示一组资源的数量,并支持计数功能。信号量分为二进制信号量(类似于互斥锁)计数信号量两种类型[^3]。 --- #### 使用场景分析 - **互斥锁** - 主要应用于单处理器或多处理器环境中,当某个线程需要长时间占用某一资源时,适合采用互斥锁[^3]。 - 场景实例:文件系统的写入操作,数据库事务处理等需要严格串行化的场合。 - **自旋锁** - 更适合于多核环境下短期锁定需求,因为其不会让出 CPU 时间片而是持续轮询锁的状态[^4]。 - 如果预计锁会被很快释放,则自旋锁是一种高效的选择;但如果锁持有时过长则会造成不必要的 CPU 资源浪费[^1]。 - 应用案例:中断处理程序之间的小范围同步问题。 - **信号量** - 当存在多个相同类型的资源共享情况时非常有用,比如生产者消费者模型中缓冲队列大小限制可以通过信号量有效解决。 - 它还解决了某些特定条件下可能出现的竞争状况,例如优先级反转等问题可通过高级特性规避[^2]。 --- #### 区别对比表 | 特性 | 互斥锁 | 自旋锁 | 信号量 | |-----------------|----------------------------------|-----------------------------------|-------------------------------------| | 是否阻塞 | 阻塞 | 不阻塞(忙等待) | 可配置为阻塞或者非阻塞 | | 开销 | 较高 | 较低 | 中等 | | 同步粒度 | 单一线程 | 多个CPU核心 | 支持多个资源 | | 死锁风险 | 存在 | 存在 | 易受错误调用序列影响 | --- #### 联系总结 尽管三者的具实现技术细节有所不同,但它们都旨在解决并发编程中的同步与互斥问题。选择哪种工具取决于实际应用场景的要求以及性能考量因素: - 对于较长期限内的独占式访问建议选用 Mutex; - 若预期等待时间极短且运行环境具备足够的计算能力可考虑 SpinLock; - Semaphore 则更适合涉及数量变化或需协调多方协作的任务情境下运用[^1]^. ```c // 示例代码展示如何初始化并使用这些同步原语 #include <pthread.h> #include <semaphore.h> pthread_mutex_t mutex; spinlock_t spin_lock; sem_t semaphore; void init_sync_primitives() { pthread_mutex_init(&mutex, NULL); // 初始化互斥锁 spin_lock_init(&spin_lock); // 初始化自旋锁 [^4] sem_init(&semaphore, 0, 1); // 初始化信号量 } void lock_and_unlock_example() { pthread_mutex_lock(&mutex); /* Critical Section */ pthread_mutex_unlock(&mutex); spin_lock(&spin_lock); /* Critical Section */ spin_unlock(&spin_lock); sem_wait(&semaphore); /* Critical Section */ sem_post(&semaphore); } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值