linux互斥锁和条件变量的关系

mutex体现的是一种竞争,我离开了,通知你进来。

cond体现的是一种协作,我准备好了,通知你开始吧。

  • 互斥锁一个明显的缺点是它只有两种状态:锁定和非锁定。而条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足,它常和互斥锁一起配合使用。使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化。一旦其他的某个线程改变了条件变量,他将通知相应的条件变量唤醒一个或多个正被此条件变量阻塞的线程。这些线程将重新锁定互斥锁并重新测试条件是否满足。一般说来,条件变量被用来进行线程间的同步。

  • 两个线程操作同一临界区时,通过互斥锁保护,若A线程已经加锁,B线程再加锁时候会被阻塞,直到A释放锁,B再获得锁运行,进程B必须不停的主动获得锁、检查条件、释放锁、再获得锁、再检查、再释放,一直到满足运行的条件的时候才可以(而此过程中其他线程一直在等待该线程的结束),这种方式是比较消耗系统的资源的。而条件变量同样是阻塞,还需要通知才能唤醒,线程被唤醒后,它将重新检查判断条件是否满足,如果还不满足,该线程就休眠了,应该仍阻塞在这里,等待条件满足后被唤醒,节省了线程不断运行浪费的资源。这个过程一般用while语句实现。当线程B发现被锁定的变量不满足条件时会自动的释放锁并把自身置于等待状态,让出CPU的控制权给其它线程。其它线程
    此时就有机会去进行操作,当修改完成后再通知那些由于条件不满足而陷入等待状态的线程。这是一种通知模型的同步方式,大大的节省了CPU的计算资源,减少了线程之间的竞争,而且提高了线程之间的系统工作的效率。这种同步方式就是条件变量。

  • 以上说明可能有点抽象,考虑这样的简单场景:通过伪代码说明。
    A线程从队列中取元素,B线程往队列中存放元素。不考虑免锁的实现。需要一个mutex用来保护队列的一致性,避免两个线程同时操作队列破坏数据结构。

当队列为空的时候,A需要不断的探测队列状态 :

while(1)
{ 
if(队列为空)
休眠10s
else
    {
        加锁
        取元素
        解锁
     }
}

这就有一个问题,可能在刚进入休眠时,B放入元素了,但仍然需要休眠完整个10s的时间。造成不必要的延迟。当然如果不sleep,也可以,但会造成不必要的CPU开销。使用基于条件变量的事件通知唤醒机制,就可以避免这些问题。

一旦B放入元素完成后就执行pthread_cond_signal(),当前阻塞的线程就会立即被唤醒开始干活儿。
while(1) {
    pthread_mutex_lock();
    pthread_cond_wait();
    取元素;
    pthread_mutex_unlock();
}
  • 条件变量都用互斥锁进行保护,条件变量状态的改变都应该先锁住互斥锁,pthread_cond_wait()需要传入一个已经加锁的互斥锁,该函数把调用线程加入等待条件的调用列表中,然后释放互斥锁,在条件满足从而离开pthread_cond_wait()时,mutex将被重新加锁,这两个函数是原子操作。
    可以消除条件发生和线程睡眠等待条件发生间的时间间隙。其他线程在获得互斥量之前不会察觉到这种改变,因为必须锁定互斥量才能计算条件。

  • 感觉可以总结为:条件变量用于某个线程需要在某种条件成立时才去保护它将要操作的临界区,这种情况从而避免了线程不断轮询检查该条件是否成立而降低效率的情况,这是实现了效率提高。。。在条件满足时,自动退出阻塞,再加锁进行操作。

  • 以上是关于效率问题,此外互斥锁还有一个缺点就是会造成死锁。
    例如线程A和线程B都需要独占使用2个资源,但是他们都分别先占据了一个资源,然后又相互等待另外一个资源的释放,这样就形成了一个死锁。

  • 条件变量起到了阻塞和唤醒线程的作用,所以通常互斥锁要和条件变量配合。
    为了解决以上问题,条件变量常和互斥锁一起使用,条件变量通过允许线程阻塞和等待另一个线程发送信号的方法弥补了互斥锁的不足。使用时,条件变量被用来阻塞一个线程,当条件不满足时,线程往往解开相应的互斥锁并等待条件发生变化。一旦其它的某个线程改变了条件变量,它将通知相应的条件变量唤醒一个或多个正被此条件变量阻塞的线程。这些线程将重新锁定互斥锁并重新测试条件是否满足。

参考原文:浅谈互斥锁为什么还要和条件变量配合使用

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Linux下的进程间通信(IPC)方式有很多种,其中无亲缘关系的进程间通信方式包括互斥锁条件变量和共享内存。 互斥锁是一种保护共享资源不被并发访问的机制。当进程需要访问共享资源时,它会尝试获取互斥锁。如果锁已经被其他进程占用,则进程会被阻塞,直到锁被释放。这样可以确保同一时间只有一个进程能够访问共享资源,从而避免了竞争条件和数据不一致的问题。 条件变量是一种进程间通信方式,用于线程同步和条件同步。使用条件变量可以实现进程的等待和唤醒操作,从而控制进程的执行顺序。当一个进程需要等待某个条件成立时,它会调用条件变量的等待操作,该操作会阻塞进程并释放对共享资源的占用。当条件满足时,其他进程可以通过唤醒操作通知等待的进程继续执行。 共享内存是一种能够在不同进程之间共享数据的机制。通过共享内存,可以将一块内存空间映射到不同的进程地址空间,从而实现进程间的数据共享。多个进程可以直接访问共享内存,从而实现高效的数据传递。但需要注意的是,由于共享内存不提供进程间同步和互斥机制,因此在使用共享内存进行进程间通信时,需要结合其他同步机制(如互斥锁)确保数据的一致性和正确性。 综上所述,互斥锁条件变量和共享内存是Linux下无亲缘关系的进程间通信的重要方式。通过这些方式,进程可以进行数据共享和同步,从而实现协作和协同操作。但在使用这些机制时,需要注意进程同步和互斥的问题,以确保数据的正确性和一致性。 ### 回答2: Linux中的进程间通信(IPC)是指不同进程之间进行数据交换和共享资源的方法。在Linux中,有多种IPC机制可以实现进程间的通信,包括管道、消息队列、信号量、共享内存和套接字等。其中,互斥锁条件变量和共享内存是常用的进程间通信方式。 互斥锁是一种同步原语,用于保护共享资源的访问。当一个进程正在使用共享资源时,可以通过申请互斥锁来锁定资源,防止其他进程同时访问。只有当拥有互斥锁的进程释放锁时,其他进程才能竞争获取锁。 条件变量通常与互斥锁一起使用,用于实现在特定条件下的线程等待和唤醒操作。一个进程可以通过条件变量来等待某个特定条件的发生,如果条件不满足,则该进程将等待在条件变量上。当另一个进程满足了条件并发送了信号时,该进程就会被唤醒。 共享内存是一种用于实现进程间数据共享的技术。它允许多个进程直接访问同一块内存区域,而无需进行数据的拷贝和传输。进程可以通过映射共享内存到自己的地址空间上来实现对共享内存区域的访问。在使用共享内存时,需要使用互斥锁等同步机制来保证多个进程对于共享内存的访问是安全的。 总之,互斥锁条件变量和共享内存是Linux中常用的进程间通信方式,它们通过提供同步机制和共享资源访问的方法,实现了不同进程之间的数据交换和资源共享。这些机制在多进程编程中非常重要,可以有效提高程序的并发性能和效率。 ### 回答3: 在Linux下,无亲缘关系的进程间通信可以利用互斥锁条件变量和共享内存来实现。以下是对每种通信方式的详细描述: 1. 互斥锁互斥锁是一种用于保护共享资源的同步机制,确保在同一时刻只有一个进程可以访问被保护的资源。在无亲缘关系的进程间通信中,可以使用互斥锁实现对共享资源的互斥访问。当一个进程想要访问共享资源时,它会先检查互斥锁的状态。如果互斥锁已被其他进程持有,则该进程将被阻塞,直到互斥锁变为可用状态。一旦该进程获得互斥锁,它就可以访问共享资源,完成操作后释放互斥锁。 2. 条件变量条件变量用于进程间的协调和同步。当一个进程需要等待某个条件满足时,它可以通过条件变量来进行等待,并在条件变量满足时被唤醒。在无亲缘关系的进程间通信中,可以使用条件变量实现多个进程之间的等待和唤醒机制。当一个进程需要等待某个条件满足时,它可以调用等待函数,将自己放入条件变量的等待队列中并阻塞。当另一个进程满足了条件后,它可以通过唤醒函数来通知等待的进程,使其重新运行。 3. 共享内存:共享内存是一种让多个进程可以访问同一块内存区域的方式。在无亲缘关系的进程间通信中,可以使用共享内存实现进程间的数据共享。多个进程可以将需要共享的数据映射到同一块共享内存区域,并利用该内存区域进行数据的读写操作。通过共享内存,进程可以直接读写共享数据,而无需通过其他的通信机制。此外,为了保证数据的一致性和并发访问的正确性,通常还需要使用互斥锁或其他同步机制来控制对共享内存的访问。 综上所述,Linux提供了互斥锁条件变量和共享内存这几种机制来实现无亲缘关系的进程间通信,进程可以通过这些通信方式来进行资源的互斥访问、进程之间的协调和同步,以及共享数据的传递。通过合理地选择和使用这些通信方式,可以实现高效、可靠的进程间通信。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值