条件变量的接口函数和使用原则

简介:

条件变量的接口、常量、数据类型

1.静态创建一个条件变量(栈)

pthread_cond_t cond;

2.动态创建一个条件变量(堆)

pthread_cond_t * pCond = (pthread_cond_t *)malloc(sizeof(pthread_cond_t));

3.初始化静态条件变量(默认方式)

使用宏 PTHREAD_COND_INITIALIZER

4.动态初始化条件变量

int pthread_init(pthread_cond_t *cond, pthread_condattr_t *condattr);

5.销毁堆上创建的条件变量

int pthread_destroy(pthread_cond_t *cond);

6.使用条件变量进行等待

int pthread_cond_wait(pthread_cond_t * cond,pthread_mutex_t *mutex);

int pthread_cond_timewait(pthread_cond_t *cond,pthread_mutex_t *mutex,struct timespec * expiration);

7.唤醒条件变量

int pthread_cond_signal(pthread_cond_t * cond);

int pthread_cond_broadcast(pthread_cond_t * cond);

 

条件变量的使用原则

条件变量不允许复制,但是可以复制其指针。

线程从条件变量醒来时,一定要检查谓语是否成立。这是因为以下三个原因造成的:

1.唤醒可能被拦截:线程A被唤醒的过程中需要重新获取互斥量,如果互斥量被线程B首先获取到了,则线程B首先执行并重置了共享数据的状态,这时候切换回线程AA在没有检查谓语成立的情况下开始操作可能导致灾难性的后果,因为此时谓语已经不成立。

2.模糊谓语:在程序中使用模糊谓语可简化逻辑,而且并不会很影响性能。这种模糊谓语可能唤醒某个线程,该线程对应的精确谓语事实上是不满足的,所以需要重新检查谓语。

3.伪唤醒:这和实现相关了,保证条件变量的唤醒完全可预测可能降低系统的整体性能,线程可能在没有任何其他线程使用signal或者broadcast的前提下唤醒,不过这种概率很小,但并不是没有可能。

尽量不要再pthreads中使用UNIX信号。

发广播可看成是对发信号通用化,也可见发信号看成是发广播的优化版。不能使用发信号取代发广播。在使用发信号的地方使用发广播是完全可以的,当然前提是所有的唤醒线程都进行谓语测试。

对于一个队列模型,如果有一个生产者,多个消费者。如果生产者一次只放入一个产品,则可以使用发信号的方式。如果生产者一次放入多个产品则可以使用发广播的方式。

在发广播或者发信号的时候对于互斥量可以加锁也可以不加锁。不加锁的好处为潜在的高效率,如果唤醒线程加锁发信号,被唤醒的线程需要尝试着获取互斥量,这时获取失败,又切换回唤醒线程。这会导致两次无意义的切换,当然这个实现可以优化的。加锁的好处在于保证高优先级的线程首先执行,如果不加锁,则所有的线程(不只是将要被唤醒的线程还可能有其他的没有使用条件变量的线程)都有可能获取当前锁。如果低优先级的条件变量首先获得了锁,高优先级的线程将不能被保证。而使用加锁的方式发广播信号之后,解锁后,系统会优先调度优先级高的线程先获得锁,因此保证了公平性(这里的公平更接近于香港廉政署的定义:公平不是每个人都赚十块钱,公平是你有赚100元的能力,社会保证你能赚100元。你有能力赚10元时,社会保证你赚10 D)。



本文转自hipercomer 51CTO博客,原文链接:http://blog.51cto.com/hipercomer/914921

相关文章
|
30天前
|
存储 安全 Linux
【C/C++ 可重入函数与不可重入函数】理解C/C++ 中函数的可重入性以及与线程安全性的关系
【C/C++ 可重入函数与不可重入函数】理解C/C++ 中函数的可重入性以及与线程安全性的关系
31 0
【C/C++ 可重入函数与不可重入函数】理解C/C++ 中函数的可重入性以及与线程安全性的关系
|
30天前
|
安全 C++ 开发者
【C++多线程同步】C++多线程同步和互斥的关键:std::mutex和相关类的全面使用教程与深度解析
【C++多线程同步】C++多线程同步和互斥的关键:std::mutex和相关类的全面使用教程与深度解析
18 0
|
4月前
|
存储 缓存 Linux
Linux驱动开发(锁和信号量的概念及实现原理)
Linux驱动开发(锁和信号量的概念及实现原理)
48 0
|
8月前
|
Java API 调度
|
Java 程序员 API
AQS抽象队列同步器
AQS抽象队列同步器
AQS抽象队列同步器
|
安全 调度 数据库
Windows开发——临界区,互斥量,信号量,事件的简单介绍与区别
Windows开发——临界区,互斥量,信号量,事件的简单介绍与区别
491 0
|
API C# Windows
C#多线程(4):进程同步Mutex类
C#多线程(4):进程同步Mutex类
213 0
C#多线程(4):进程同步Mutex类
|
算法 Java
Java并发编程之AbstractQueuedSychronizer(抽象队列同步器,简称AQS)
Java并发编程之AbstractQueuedSychronizer(抽象队列同步器,简称AQS)
126 0
|
Linux
Linux系统编程-(pthread)线程的使用案例(分离属性、清理函数等)
这篇文章介绍Linux下线程的创建与基本使用案例,主要是案例代码为主;相关的函数详细介绍在上篇文章里已经介绍过了。
189 0