gpt4 book ai didi

c - pthreads 中丢失唤醒

转载 作者:太空宇宙 更新时间:2023-11-04 08:43:55 25 4
gpt4 key购买 nike

我编写了一些程序来尝试 pthread 条件等待。但问题是,不能保证发出信号时会被捕获,从而使线程失去唤醒。我该如何解决这个问题?

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

pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void *thread_func1(void* arg){
printf("thread1 started\n");
pthread_mutex_lock(&mutex);
printf("thread1: signalling\n");
pthread_cond_signal(&cond);
printf("thread1: signalled\n");
pthread_mutex_unlock(&mutex);
printf("thread1: exiting\n");
pthread_exit(0);
}

void *thread_func2(void* arg){
printf("thread2 started\n");
pthread_mutex_lock(&mutex);
printf("thread2: waiting for signal..\n");
pthread_cond_wait(&cond, &mutex);
printf("thread2: signal received\n");
pthread_mutex_unlock(&mutex);
printf("thread2: exiting\n");
pthread_exit(0);
}

int main(int argc, char** argv){
pthread_t thread1, thread2;

pthread_create(&thread1, NULL, thread_func1, NULL);
pthread_create(&thread2, NULL, thread_func2, NULL);

pthread_join(thread1, 0);
pthread_join(thread2, 0);

return 0;
}

这是运行的输出:

thread1 started
thread1: signalling
thread2 started
thread2: waiting for signal..
thread1: signalled
thread1: exiting
// nothing happens now; where is the signal??

这是另一个(有效):

thread2 started
thread2: waiting for signal..
thread1 started
thread1: signalling
thread1: signalled
thread1: exiting
thread2: signal received
thread2: exiting
// program successfully exits

我现在不关心任何类型的临界区,所以我没有使用任何锁。

我如何确保它对每次运行都有效?

编辑:我已经按照下面 alk 的回答编辑了代码。我已经添加了初始化器和锁。我发布的原始代码是here .

最佳答案

如您所见,线程 1 可能会在线程 2 调用 pthread_cond_wait() 之前通知条件变量。条件变量不会“记住”它已收到信号,因此唤醒将丢失。因此,需要使用某种变量来判断线程2是否需要等待。

int signalled = 0;

void *thread_func1(void* arg){
printf("thread1 started\n");
pthread_mutex_lock(&mutex);
printf("thread1: signalling\n");
signalled = 1;
pthread_cond_signal(&cond);
printf("thread1: signalled\n");
pthread_mutex_unlock(&mutex);
printf("thread1: exiting\n");
pthread_exit(0);
}

void *thread_func2(void* arg){
printf("thread2 started\n");
pthread_mutex_lock(&mutex);
printf("thread2: waiting for signal..\n");
if(!signalled) {
pthread_cond_wait(&cond, &mutex);
}
printf("thread2: signal received\n");
pthread_mutex_unlock(&mutex);
printf("thread2: exiting\n");
pthread_exit(0);
}

但是,这段代码仍然不正确。 pthreads 规范声明“虚假唤醒”可能发生在条件变量上。这意味着 pthread_cond_wait() 可能会返回,即使没有人调用过 pthread_cond_signal()pthread_cond_broadcast()。因此,您需要循环检查标志,而不是只检查一次:

void *thread_func2(void* arg){
printf("thread2 started\n");
pthread_mutex_lock(&mutex);
printf("thread2: waiting for signal..\n");
while(!signalled) {
pthread_cond_wait(&cond, &mutex);
}
printf("thread2: signal received\n");
pthread_mutex_unlock(&mutex);
printf("thread2: exiting\n");
pthread_exit(0);
}

更新:另一种结合条件变量和计数器功能的方法是使用信号量。

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
sem_t sem;

void *thread_func1(void* arg){
printf("thread1 started\n");
printf("thread1: signalling\n");
sem_post(&sem);
printf("thread1: signalled\n");
printf("thread1: exiting\n");
pthread_exit(0);
}

void *thread_func2(void* arg){
printf("thread2 started\n");
printf("thread2: waiting for signal..\n");
sem_wait(&sem);
printf("thread2: signal received\n");
printf("thread2: exiting\n");
pthread_exit(0);
}

int main(int argc, char** argv){
pthread_t thread1, thread2;

sem_init(&sem);

pthread_create(&thread1, NULL, thread_func1, NULL);
pthread_create(&thread2, NULL, thread_func2, NULL);

pthread_join(thread1, 0);
pthread_join(thread2, 0);

sem_destroy(&sem);

return 0;
}

关于c - pthreads 中丢失唤醒,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22427493/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com