当前位置:首页 > 技术知识 > 正文内容

Linux系统编程:条件变量为什么要用锁

maynowei2周前 (08-03)技术知识13

条件变量可以解决线程同步和共享资源访问的问题,条件变量是对互斥锁的补充,它允许一个线程阻塞并等待另一个线程发送的信号,当收到信号时,阻塞的线程被唤醒并试图锁定与之相关的互斥锁。具体定义如下:

等待:

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

int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abtime);

唤醒:

int pthread_cond_signal(pthread_cond_t *cond);

int pthread_cond_broadcast(pthread_cond_t *cond);

具体使用场景:

在等待线程实现如下:

pthread_mutex_lock(&same_mutex);

pthread_cond_wait(&m_cond, &same_mutex);

pthread_mutex_unlock(&same_mutex);

在唤醒线程实现如下:

pthread_mutex_lock(&same_mutex);

pthread_cond_signal(&m_cond);

pthread_mutex_unlock(&same_mutex);

等待线程会在pthread_cond_wait()调用时挂起,并且在锁的保护下构造和检查好m_cond对应的条件链表后先解锁same_mutex,然后睡眠。这里解锁和睡眠是一个原子操作。当等待线程收到唤醒线程的通知后,pthread_cond_wait做的第一件事是把same_mutex重新加锁并唤醒返回,这里加锁和唤醒也是一个原子操作。

那么唤醒线程和等待线程为什么要用同一个mutex锁呢?首先,如果在等待线程调用了pthread_cond_wait()但是还没有开始等待(因为之前还要做链表的初始化工作),这时唤醒操作如果发生则会导致唤醒丢失(竞态条件)。因此必须使用锁防止条件链表这个共享资源被同时操作。(等待线程先在锁保护下操作完共享链表,然后解锁和睡眠是原子操作后开始睡眠,因此唤醒操作如果是在同一把锁保护中才能唤醒的话(唤醒也会修改共享链表),等待线程一定已经访问完共享资源并且睡眠了,就防止了冲突丢失唤醒信号)。 但是如果当前没有线程阻塞等待唤醒,pthread_cond_signal()函数调用后应没有任何效果。

因此条件变量使用锁是为了防止唤醒和等待操作同时发生的竞态条件,从而导致唤醒丢失甚至引起死锁。但是如果是认为不等待直接唤醒则该唤醒会直接丢失。

注:

最后pthread_cond_wait唤醒和加锁也是一个原子操作,如果有多个线程在同一个条件变量上等待,可以保证虽然都被唤醒了但是只有一个线程会获取到锁。

相关文章

如何快速将axure生成的原型放到手机上演示

人人都是产品经理旗下【起点学院】推出产品经理“365天”成长计划,BAT大牛带你学产品! 之前Axure官方有一个原型在线分享演示的平台,用户可以直接生成原型到Axure官方平台,方便用户提供演示:h...

验证码,除了 12306,我还没有服过谁

为了防止暴力注册或爬虫爬取等机器请求,需要验证操作者是人还是机器,便有了验证码这个设计。本文作者主要介绍了如何使用 Axure 来设计一个动态的图形验证码,一起来学习一下吧。在软件设计中,为了防止暴力...

msf系列篇章之七模块详解,黑客必学

1、 mestasploit有很多模块,一共分为七类那如果是kali中自带的msf,它默认的安装路径是在这里。,然后可以看见它这些模块有些相对应的目录。1)、exploits漏洞利用模块,这个模块通常...

那些技术—Listview的性能提高篇(listview提高效率)

ListView优化一直是一个老生常谈的问题,不管是面试还是平常的开发中,ListView永远不会被忽略掉,那么这篇文章我们来看看如何最大化的优化ListView的性能。 · 1.在adapter中的...

Xamarin.Android使用教程:列表视图和适配器(2)

昨天我们已经一起学习了第1部分,这是探索Xamarin.Android的列表视图和适配器的的第2部分。在今天的文章中我们将探讨列表视图项排列使用BaseAdapter,还有自定义布局。让我们深入到代码...

如何优雅地使用嵌入式事件标志组?

事件标志组嵌入式事件标志组是一种在嵌入式系统中广泛使用的同步机制,主要用于实现多任务间的同步与通信。事件标志组是一组事件标志位的集合,每个位代表一个事件是否发生。它允许任务等待特定的事件发生,当事件发...