c - 为什么此代码返回意外结果? (条件变量)

标签 c linux mutex

正在研究互斥锁。

所以,我写了关于互斥锁的测试代码。

但是这段代码有问题。

我想展示:

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/

相关文章:

c++ - 这应该称为互斥体吗?

multithreading - 线程因锁定的互斥锁而崩溃

c - 如何模拟内存分配错误

c - 使用 strcpy 和 strcat 时堆栈粉碎

c - 我如何链接 GLFW

使用 Linux netfilter 将源 IP 地址从 struct iphdr* 转换为等效字符串

c - 如何在c中从字符串中分离和存储元素?

linux - SVN。访问权

linux - 是否可以按确切日期查找文件然后对结果文件执行 tar 命令?

c++ - 在 C++11 中,是否有 std::lock_guard 的变体在构造时解锁并在销毁时锁定?