正在研究互斥锁。
所以,我写了关于互斥锁的测试代码。
但是这段代码有问题。
我想展示:
downloading.....
complete....
start play!
但是在运行时,结果是:
downloading.....
complete....
我不知道 1.为什么这段代码有错误? 2.如何修复这段代码?
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
int buffer = 0;
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void* download(void *arg){
printf("downloading.....\n");
pthread_mutex_lock(&lock);
sleep(3);
buffer = 10;
printf("complete....\n");
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
return NULL;
}
void* play(void *arg){
pthread_mutex_lock(&lock);
pthread_cond_wait(&cond, &lock);
printf("start play!\n");
--buffer;
pthread_mutex_unlock(&lock);
return NULL;
}
int main(){
pthread_t tid1, tid2;
pthread_create(&tid1, NULL, play, NULL);
pthread_create(&tid2, NULL, download, NULL);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
}
最佳答案
download()
函数恰好首先运行,获取互斥量并完成其所有工作(包括在释放互斥量之前调用 pthread-cond_signal()
。
play()
线程在信号发送之前没有机会调用pthread_cond_wait()
,因为download()
恰好获取了首先互斥。所以当 play()
有机会等待时,它已经错过了唤醒它的信号。
修复方法是将条件变量与标志(可能是 buffer
- 取决于您实际想要做什么)结合使用。需要用标志完成几件事:
- 在调用
pthread_cond_wait()
之前必须检查标志,如果标志表明条件已经满足,则不不应该等待 - “仅当条件未满足时才检查标志/等待”操作应该在循环中执行,因为
pthread_cond_wait()
可能会虚假返回(即,没有发出信号) - 标志检查和对标志的任何更新(在任何线程中)都必须在持有互斥锁的同时完成
类似于(以下代码未经测试):
void* play(void *arg)
{
pthread_mutex_lock(&lock);
while (buffer < 1) {
pthread_cond_wait(&cond, &lock);
}
printf("start play!\n");
--buffer;
pthread_mutex_unlock(&lock);
return NULL;
}
关于c - 为什么此代码返回意外结果? (条件变量),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49664363/