【问题标题】:Condition variables in cc中的条件变量
【发布时间】:2021-12-28 11:22:10
【问题描述】:

我刚开始学习线程、互斥体和条件变量,我有以下代码:


#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

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

【问题讨论】:

  • 改用rand % 100
  • 不要使用-lpthread,它只链接libpthread。而是在编译和链接时都使用-pthread,这不仅会导致链接所有需要的附加库,还会影响代码生成。

标签: c pthreads locking mutex condition-variable


【解决方案1】:

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

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

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

thread_one_function 线程没有终止的原因很明确,我相信如果你寻找它,你会认出它。但是thread_two_function 线程呢?需要很长时间才能终止的原因至少有两个:

  • 更明显的是@dbush 对这个问题的评论中暗示的那个。考虑rand() 函数的范围:您认为它可能需要多少次调用才能返回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 并不是完全错误,但它是无关紧要的。

【讨论】:

    猜你喜欢
    • 2010-12-31
    • 2021-10-25
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-13
    • 2015-07-01
    • 1970-01-01
    相关资源
    最近更新 更多