深入Phtread(三):线程的同步-Condition Variables

本文详细介绍了Phtread中的条件变量概念及其在多线程间的应用。通过实例讲解了条件变量的创建、等待、唤醒等操作,帮助读者更好地理解和运用线程同步机制。

深入Phtread(三):线程的同步-Condition Variables


    继续昨天的线程同步,条件变量(Condition Variables)是用于线程间,通信共享数据状态改变的机制。

简介

    当线程互斥地访问一些共享的状态时,往往会有些线程需要等到这些状态改变后才应该继续执行。如:有一个共享的队列,一个线程往队列里面插入数据,另一个线程从队列中取数据,当队列为空的时候,后者应该等待队列里面有值才能取数据。而共享数据(队列)应该用mutex来保护,为了检查共享数据的状态(队列是否为空),线程必须先锁定mutex,然后检查,最后解锁mutex。
 
    问题出来了:当另外一个线程B锁定mutex后,往队列里面插入了一个值,B并不知道A在等着它往队列里面放入一个值。,线程A(等待状态改变)一直在运行,线程B可能已经检查过队列是空的,并不知道队列里已经有值了,所以一直阻塞着自己。为了解决这样的问题引入了条件变量机制。线程B等待于一个条件变量,当线程A插入了一个值后,signal或broadcast这个条件变量,通知线程B状态已改变,A发现条件变量被signaled了,就继续执行。就这样,当一个线程改变共享数据状态后,可以及时通知那些等待于该状态的线程。图示下:
 

    中间的矩形代表条件变量,当线程线位于矩形内,表示线程等待该条件变量。位于中心线下下方,则表示signal了该条件变量。
    开始线程1 signal 了条件变量,由于没有其他线程等待于该条件变量,所以没什么效果。然后,线程1和线程2先后等待该条件变量,过了一会,线程3 signal了条件变量,线程3的信号解除了线程1的阻塞。然后,线程3等待该条件变量。最后线程1 broadcast了该条件变量,同时解除了等待于条件变量的线程1和线程2。
 


条件变量的创建和销毁

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int pthread_cond_init(pthread_cond_t* cond, pthread_condattr_t* condattr);
int pthread_cond_destroy(pthread_cond_t* cond);
 
和互斥量一样,可以动态创建和静态创建。
静态创建:条件变量声明为extern或static变量时。
例程:
 
动态创建:一般情况下,条件变量要和它的判定条件定义在一起,此时若包含该条件变量的数据动态创建了,则条件变量也需要动态创建,不过记得不用时用pthread_cond_destroy销毁。
 
例程:
 

等待条件变量

int pthread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex);
int pthread_cond_timedwait(pthread_cond_t* cond, pthread_mutex_t* mutex, struct timespec* expiration);
 
    条件变量与互斥量一起使用,调用pthread_cond_wait或pthread_cond_timedwait时,记得在前面锁定mutex,尽可能多的判断判定条件。上面提到的两个等待条件变量的函数,显示解锁mutex,然后阻塞线程等待状态改变,等待的条件变量signaled后,锁定mutex,返回。记着,这两个函数返回时,mutex一定是锁定的。
 
多个条件变量可以共享一个互斥变量,相反则不成立。
 
例程:
 
 

唤醒等待条件变量的线程

 
int pthread_cond_signal(pthread_cond_t* cond);
int pthread_cond_broadcast(pthread_cond_t* cond);
 
    一但有线程由于某些判定条件(predicate)没满足,等待条件变量。我们就有必要当条件满足时,发送信号去唤醒这些线程。
    注意:broadcast通常很容易被认为是signal的通用版,其实不能这样理解,准确一点应该说,signal是broadcast的优化版。具体区别不大,但signal效率较broadcast高些。但你不确信有几个线程等待条件变量时用broadcast(When in doubt, broadcast!)。
 
例程:

 

 

author: david( heaven.hell.or@gmail.com)

 

在 Android 的 `bugreport.txt` 文件中,你提到的两行内容: ``` ---- State variables set externally ---- ---- State variables calculated internally ---- ``` 通常出现在 **Dumpsys 输出的某个系统服务状态中**,例如 `dumpsys notification`、`dumpsys activity` 或其他服务模块中。它们用于区分 **状态变量的来源**。 --- ### 🔍 行 5782: `---- State variables set externally ----` 这行表示接下来列出的变量是 **由外部设置的**,即: - 由用户设置(如在设置中更改通知优先级) - 由应用配置(如调用 `setImportance()`) - 由系统策略(如设备管理员设置) **示例内容:** ```txt importance=2 soundEnabled=true vibrateEnabled=false ``` --- ### 🔍 行 5789: `---- State variables calculated internally ----` 这行表示接下来列出的变量是 **系统内部计算得出的**,即: - 根据当前设备状态(如是否在“请勿打扰”模式)动态计算 - 受其他服务状态影响(如 Do Not Disturb 状态、设备焦点状态) **示例内容:** ```txt effectiveImportance=3 suppressedVisualEffects=true showInQuietMode=false ``` --- ### 🧠 举例说明(以 Notification 服务为例) ```txt ---- State variables set externally ---- importance=2 soundUri=content://settings/system/notification_sound bypassDnd=false ---- State variables calculated internally ---- effectiveImportance=3 suppressedVisualEffects=true ``` - `importance=2` 是用户设置的优先级。 - `effectiveImportance=3` 是系统根据当前 Do Not Disturb 模式计算出的实际优先级。 - `suppressedVisualEffects=true` 表示视觉效果(如通知灯)被系统策略屏蔽。 --- ### 📌 实际用途 | 场景 | 用法 | |------|------| | **调试通知行为异常** | 查看 `effectiveImportance` 是否被系统策略覆盖 | | **排查声音/震动不生效** | 对比 `soundEnabled`(用户设置)和 `effectiveSoundEnabled`(实际效果) | | **分析通知是否被屏蔽** | 查看 `suppressedVisualEffects` 和 `showInQuietMode` | | **确认用户设置是否生效** | 检查 `set externally` 块中的变量是否被正确保存 | --- ### 🧰 如何查看这些状态变量? 你可以使用以下命令查看特定服务的状态: ```bash adb shell dumpsys notification adb shell dumpsys activity adb shell dumpsys window ``` 然后在输出中搜索: ```bash grep -A 10 "State variables set externally" bugreport.txt grep -A 10 "State variables calculated internally" bugreport.txt ``` ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值