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 并非完全错误,但它是无关紧要的。
我刚开始学习线程、互斥锁和条件变量,我有这段代码:
#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 并非完全错误,但它是无关紧要的。