Linux互斥量&条件变量

互斥量 Mutex

互斥量
1. #include <pthread.h>  
2. int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *mutexattr);  
3.   
4. int pthread_mutex_lock(pthread_mutex_t *mutex);  
5.   
6. int pthread_mutex_unlock(pthread_mutex_t *mutex);  
7.   
8. int pthread_mutex_destroy(pthread_mutex_t *mutex);

linux中创建使用互斥量的方法如上,对于此和windows中非常类似,用于保护对于临界资源的互斥性访问。
如果将此互斥量放在进程的共享内存里,那么还可以通过此种方法实现进程的互斥访问,通过pthread_mutexattr_setpshared()来实现:
9. pthread_mutex_t *pSharedMutex;  //指向共享内存区的互斥量  
10. pthread_mutexattr_t mutexAttr;  //互斥量属性  
11.   
12. pSharedMutex = /*一个指向共享内存区的指针*/;  
13.   
14. pthread_mutexattr_init(&mutexAttr);  
15. pthread_mutexattr_setpshared(&mutexAttr, PTHREAD_PROCESS_SHARED);  
16. pthread_mutex_init(pSharedMutex, &mutexAttr);

对于另外一些情况,比如在生产者和消费者模型中,如果使用互斥量来进行同步,那么每次在获取互斥量以后,线程还需要检测当前资源是否符合条件,不符合退出,这会造成轮询来浪费cpu的时间,对于这种情形应该使用条件变量

条件变量
条件变量用来等待,自动堵塞一个线程,直到指定的事件发生:
int pthread_cond_init(pthread_cond_t *cond,pthread_condattr_t *cond_attr);
int pthread_cond_wait(pthread_cond_t *cond,pthread_mutex_t *mutex);
int pthread_cond_timewait(pthread_cond_t *cond,pthread_mutex *mutex,const timespec *abstime);
int pthread_cond_destroy(pthread_cond_t *cond);
int pthread_cond_signal(pthread_cond_t *cond);
int pthread_cond_broadcast(pthread_cond_t *cond); //解除所有线程的阻塞

条件变量使用上面的接口进行实现,需要注意的是要和一个mutex绑定进行使用,

#include <pthread.h>
#include <stdio.h>
#include<unistd.h>
#include <stdbool.h>
pthread_cond_t c = PTHREAD_COND_INITIALIZER;
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;

bool con = false;

void thread()
{
printf("%s\n", "child thread begin");

pthread_mutex_lock(&m);
while(!con) //避免虚假唤醒
pthread_cond_wait(&c, &m);
printf("%s\n", "child thread return");
pthread_mutex_unlock(&m);
}

int main()
{
pthread_t id;
int ret = pthread_create(&id, NULL, (void*)thread, NULL);
if(ret != 0)
{
printf("%s\n", "thread create failed");
}

sleep(1);
pthread_mutex_lock(&m);
printf("%s\n", "main thread");
pthread_mutex_unlock(&m);
con = true;
pthread_cond_signal(&c);
printf("%s\n", "main thread signal end");

pthread_join(id, NULL);
return 1;

}

pthread_cond_wait 执行的流程首先将这个mutex解锁, 然后等待条件变量被唤醒, 如果没有被唤醒, 该线程将一直休眠, 也就是说, 该线程将一直阻塞在这个pthread_cond_wait调用中, 而当此线程被唤醒时, 将自动将这个mutex加锁,然后再进行条件变量判断(原因是“惊群效应”,如果是多个线程都在等待这个条件,而同时只能有一个线程进行处理,此时就必须要再次条件判断,以使只有一个线程进入临界区处理。),如果满足,则线程继续执行,最后解锁,

需要注意:
唤醒丢失问题 
在线程并没有阻塞在条件变量上时,调用pthread_cond_signal或pthread_cond_broadcast函数可能会引起唤醒丢失问题。
唤醒丢失往往会在下面的情况下发生:
一个线程调用pthread_cond_signal或pthread_cond_broadcast函数; 
另一个线程正处在测试条件变量和调用pthread_cond_wait函数之间; 
没有线程正在处在阻塞等待的状态下。

调用pthread_cond_wait 前,要在函数外先锁住一个mutex,然后传给pthread_cond_wait 。
我知道,这样可以关闭 “条件检查与加入等待队列之间的时间窗”,
线程休眠前释放锁,醒来后再次加锁。
即:
加锁                     pthread_cond_wait  外
------------------- |----------------------------
1 判断条件             |
2 加入休眠队列 释放锁  | pthread_cond_wait 内
3 醒来         加锁    |

因为锁的存在,1,2是一个连续的操作,防止一二之间另一个线程使得条件满足

时间: 2024-12-13 20:20:48

Linux互斥量&条件变量的相关文章

多个生产者——多个消费者模型(互斥量条件变量实现)

1. 介绍 生产者消费者问题属于有界缓冲区问题.我们现在讲述多个生产者向一个缓冲区中存入数据,多个生产者从缓冲区中取数据. 共享缓冲区作为一个环绕缓冲区,存数据到头时再从头开始. 2. 实现 我们使用一个互斥量保护生产者向缓冲区中存入数据. 由于有多个生产者,因此需要记住现在向缓冲区中存入的位置. 使用一个互斥量保护缓冲区中消息的数目,这个生产的数据数目作为生产者和消费者沟通的桥梁. 使用一个条件变量用于唤醒消费者.由于有多个消费者,同样消费者也需要记住每次取的位置. 4.代码 在选项中选择生产

linux多线程:条件变量

转自 http://blog.csdn.net/hongmy525/article/details/5194006 #include <pthread.h>#include <stdio.h>#include <stdlib.h>pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;/*初始化互斥锁*/pthread_cond_t cond = PTHREAD_COND_INITIALIZER;/*初始化条件变量*/void

Linux多线程编程-条件变量

条件变量 如果说线程间的互斥锁是用来同步共享数据的访问的话,那么条件变量是用于线程之间共享数据的值.条件变量提供了一种线程之间的通知机制,当某个共享数据达到某个值时,唤醒等待这个共享数据的线程.条件变量相关函数主要 有5个: #include <pthread.h> int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr); int pthread_cond_destroy(pthread_

互斥和条件变量区别

互斥量(mutex)从本质上说是一把锁,在访问共享资源前对互斥量进行加锁,在访问完成后释放互斥量上的锁.对互斥量进行加锁以后,任何其他试图再次对互斥锁加锁的线程将会阻塞直到当前线程释放该互斥锁.如果释放互斥锁时有多个线程阻塞,所有在该互斥锁上的阻塞线程都会变成可运行状态,第一个变为运行状态的线程可以对互斥锁加锁,其他线程将会看到互斥锁依然被锁住,只能回去再次等待它重新变为可用. 条件变量(cond)是在多线程程序中用来实现"等待–>唤醒"逻辑常用的方法.条件变量利用线程间共享的全

关于互斥锁,条件变量的内核源码解析

一.解决问题和适用范围 主要是用来等待一个条件,这个条件可能需要另一个线程来满足这个条件.这个和我们平常适用的pthread_mutex_lock的最大不同在于后者保护的一般是一个代码段(也就是关键区),或者一个变量,但是由于一般来说这个变量的访问是在一个关键区中,所以可以认为是一个关键区. 但是对于条件变量,是需要的是一个事件,只有事件满足的时候才会执行后面的操作,此时就出现一个问题:如果不满足我们应该怎么办?如果如果使用简单信号量,可能另一方触发了这个条件,然后通过unlock来唤醒一个线程

Linux下用条件变量实现多线程间生产者与消费者问题

一. 线程间的同步还有这样一种情况:线程A需要等某个条件成立才能继续往下执行,现在这个条件不成立,线程A就阻塞等待,线程B在执行过程中使这个条件成立了,就唤醒线程A继续执行.在pthread库中通过条件变量(Condition Variable)来阻塞等待某个条件,或者唤醒等待这个条件的线程.Condition Variablepthread_cond_t类型的变量表,可以这样初始化和销毁: 返回值:成功返回0,失败返回错误号. 一个Condition Variable总是和一个Mutex搭配使

线程同步和互斥(条件变量控制生产者消费者模型)

条件变量 生产者消费者模型: 关系:      同步 生产者<----->消费者    互斥 互斥 生产者<----->生产者       互斥 消费者<----->消费者   场所:   缓冲区,下文以链表方式实现 1.单个生产者,单个消费者,且生产者和消费者访问链表的顺序是LIFO的 代码实现: #include<stdio.h> #include<pthread.h> pthread_mutex_t _mutex_lock=PTHREAD_

线程同步与互斥之条件·变量

条件变量(condition variable) 线程间的同步与互斥技术,主要以互斥锁和条件变量为主,条件变量和互斥所的配合使用可以很好的处理对于条件等待的线程间的同步问题.举个例子:消费者和生产者问题. 消费者与生产者最基本的关系是服务与被服务的关系,但是在线程同步与互斥中强调的是两者访问资源的关系.首先生产与消费的关系为:同步与互斥,生产与生产的关系为:互斥,消费与消费的关系为:互斥.所以维护这三种关系的有两类人:生产者与消费者.并且生产数据与消费数据必须有场所. 所以将其简述为三种关系两类

Linux Condition Variable条件变量避免锁冲突

条件变量Condition Variable的一般用法: 唤醒用法: 1 struct { 2 pthread_mutex_t mutex; 3 pthread_cond_t cond; 4 //whatever variables maintain the condition 5 ) var = { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, ... };//声明结构体并初始化 6 7 pthread_mutex_lock(&var