【pthread系列-7】条件变量的接口函数和使用原则

 

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

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元时,社会保证你赚10D)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值