c 中的条件变量

Condition variables in c

我刚开始学习线程、互斥锁和条件变量,我有这段代码:


#include <pthread.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>

static pthread_cond_t cond = PTHREAD_COND_INITIALIZER; 
static pthread_mutex_t mutex; 
static pthread_mutexattr_t attr;

volatile int x = 0;

void *thread_one_function (void *dummy) {
    printf("In func one.");
    while (true) {
        pthread_mutex_lock (&mutex);
        x = rand ();
        pthread_cond_signal (&cond);
        pthread_mutex_unlock (&mutex);
    }
}

void *thread_two_function (void *dummy) {
    printf("In func two.");
    pthread_mutex_lock (&mutex);
    while (x != 10) {
        pthread_cond_wait (&cond, &mutex);
    }
    printf ("%d\n", x);
    pthread_mutex_unlock (&mutex);
    printf ("%d\n", x);
}

int main (void){
    pthread_mutexattr_init (&attr);
    pthread_mutexattr_settype (&attr, PTHREAD_MUTEX_RECURSIVE);
    pthread_mutex_init (&mutex, &attr);

    pthread_t one, two;
    pthread_create(&one,NULL,thread_one_function,NULL);
    pthread_create(&two,NULL,thread_two_function,NULL);

    //pthread_join(one,NULL); //with this program will not end.
    //pthread_join(two,NULL);

    return 0;
}

我编译成gcc prog.c -lpthread -o a.exe

我没有得到任何输出。甚至我的线程都没有进入这两个函数...... 我究竟做错了什么 ?我的代码是作为多个文档的组合创建的。 感谢您的帮助。

您没有输出的最可能原因是主线程 returns 从初始调用到 main() 启动线程后立即。这将终止程序,包括新创建的线程。

线程的初始消息没有以换行符结尾,线程在 printf 调用后刷新标准输出也无济于事。连接到终端时,标准输出是行缓冲的,因此在您的示例中,这些消息到终端的实际传递将被推迟。

主线程在终止之前应该加入其他两个线程。您的代码注释表明您在执行此操作时遇到了其他问题,但是如果您实际上希望其他线程 运行 完成,那么不加入这些线程就不是正确的解决方案。问题不是加入线程,而是线程没有终止。

thread_one_function 线程没有终止的原因很明确,我相信如果您查找它,您会发现这一点。但是 thread_two_function 线程呢?需要很长时间才能终止的原因至少有两个:

  • 更明显的是@dbush 对该问题的评论中暗示的那个。考虑 rand() 函数的范围:您认为在 returns 之前可能需要调用多少次 thread_two_function 正在寻找的特定结果?

  • 此外,thread_two_function 多久有机会检查一次?考虑:thread_one_function 运行一个紧密循环,在该循环中它在顶部获取互斥量并在底部释放它。 Pthreads 互斥锁不执行任何类型的公平策略,因此当 thread_one_function 循环并尝试在释放互斥锁后立即重新获取它时,它立即成功的可能性非常高,即使 thread_two_function 可能是也试图获取互斥量。

轮流讨论会更有意义。也就是说,在生成一个新号码后,thread_one_function 会等待 thread_two_function 检查它,然后再生成另一个号码。有几种方法可以实现它。有些涉及在 thread_one_function 中使用与在 thread_two_function 中相同的条件变量。 (细节作为练习。)我建议还提供一种方法,thread_two_function 可以告诉 thread_one_function 它不需要生成更多数字,而是应该终止。

最后,请注意 volatile 在这里没有特别的位置。它对同步没有用或不合适,而互斥体本身就足够了。声明 x volatile 并非完全错误,但它是无关紧要的。