我正在尝试学习如何在C中正确使用条件变量。作为我自己的练习,我正在尝试制作一个小程序,其中有两个线程在无尽的环中打印" ping",然后是" pong"。
我写了一个小程序:
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void* T1(){
printf("thread 1 startedn");
while(1)
{
pthread_mutex_lock(&lock);
sleep(0.5);
printf("pingn");
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
pthread_cond_wait(&cond,&lock);
}
}
void* T2(){
printf("thread 2 startedn");
while(1)
{
pthread_cond_wait(&cond,&lock);
pthread_mutex_lock(&lock);
sleep(0.5);
printf("pongn");
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
}
}
int main(void)
{
int i = 1;
pthread_t t1;
pthread_t t2;
printf("mainn");
pthread_create(&t1,NULL,&T1,NULL);
pthread_create(&t2,NULL,&T2,NULL);
while(1){
sleep(1);
i++;
}
return EXIT_SUCCESS;
}
运行此程序时,我将获得的输出是:
main
thread 1 started
thread 2 started
ping
任何想法该程序不预期执行的原因是什么?
预先感谢。
sleep
采用整数,而不是浮点。不确定sleep(0)
在您的系统上做什么,但这可能是您的问题之一。
您需要在调用pthread_cond_wait
时握住Mutex。
裸露的条件变量(这是条件变量,没有表明在其他地方有读取的条件(几乎总是错误的。条件变量表明我们正在等待的东西可能已经准备好被消耗,它们不是用于信号的(不是因为它是非法的,而是因为很难让它们正确的纯信号传递(。因此,总的来说,条件会如下所示:
/* consumer here */
pthread_mutex_lock(&something_mutex);
while (something == 0) {
pthread_cond_wait(&something_cond, &something_mutex);
}
consume(something);
pthread_mutex_unlock(&something_mutex);
/* ... */
/* producer here. */
pthread_mutex_lock(&something_mutex);
something = 4711;
pthread_cond_signal(&something_cond, &something_mutex);
pthread_mutex_unlock(&something_mutex);
拿着锁时睡觉是个坏主意。
T1
和 T2
不是用作pthread_create
功能的有效功能,它们应该进行参数。做对了。
您在cond_signal和cond_wait之间都在每个线程中赛车,因此每个线程可能一直自称自身发出信号是不可能的。(正确地将Mutex握在pthread_cond_wait的电话中可能会有所帮助,或者可能没有帮助,这就是为什么我说正确的变量很难,因为它很难(。
首先,您永远不要使用sleep((同步线程(如果需要降低输出速度,请使用nanosleep()
(。您可能需要(常用(共享变量ready
,以便每个线程都知道他可以打印消息。在制作pthread_cond_wait()
之前,必须获得锁定,因为 pthread_cond_wait((函数应在条件变量上阻止。它应以呼叫线或未定义的行为结果锁定的穆特克斯来调用。
步骤是:
- 获取锁
- 在Guard [*] 中使用共享变量,请使用等待一段时间
- 做事
- 更改共享变量的值进行同步(如果您有一个(,并将完成工作的信号/广播
- 释放锁
步骤4和5可以逆转。
[*] 您使用 pthread_cond_wait()
释放互斥品并阻止条件变量上的线程,当使用条件变量时,总有一个布尔谓词,涉及与每个条件相关的共享变量等待,如果线程应为true,则继续进行,因为可能会发生虚假的唤醒。在这里观看更多
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int ready = 0;
void* T1(){
printf("thread 1 startedn");
while(1)
{
pthread_mutex_lock(&lock);
while(ready == 1){
pthread_cond_wait(&cond,&lock);
}
printf("pingn");
ready = 1;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
}
}
void* T2(){
printf("thread 2 startedn");
while(1)
{
pthread_mutex_lock(&lock);
while(ready == 0){
pthread_cond_wait(&cond,&lock);
}
printf("pongn");
ready = 0;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock);
}
}
int main(void)
{
int i = 1;
pthread_t t1;
pthread_t t2;
printf("mainn");
pthread_create(&t1,NULL,&T1,NULL);
pthread_create(&t2,NULL,&T2,NULL);
pthread_join(t1,NULL);
pthread_join(t2,NULL);
return EXIT_SUCCESS;
}
您还应在main
中使用pthread_join()
,而不是while(1)