我写了一个写了一个程序,它没有像我期望的那样工作.
我有两个线程:thread triggers func和anotherThread触发anotherFunc.我想要做的是当cont在func中达到值10,使用pthread_cond_wait和pthread_cond_signal触发另一个Thread.奇怪的是,如果我取消注释sleep(1)行,一切正常.我是线程的新手,我正在按照教程 here进行操作,如果我在他们的示例中评论睡眠线,它也会断开.
我有两个线程:thread triggers func和anotherThread触发anotherFunc.我想要做的是当cont在func中达到值10,使用pthread_cond_wait和pthread_cond_signal触发另一个Thread.奇怪的是,如果我取消注释sleep(1)行,一切正常.我是线程的新手,我正在按照教程 here进行操作,如果我在他们的示例中评论睡眠线,它也会断开.
我的问题是如何在没有任何sleep()调用的情况下完成这项工作?如果在我的代码中,两个func在anotherFunc之后到达pthread_mutex_lock会发生什么?我该如何控制这些东西?这是我的代码:
#include <iostream> #include <stdlib.h> #include <stdio.h> #include <pthread.h> pthread_mutex_t myMutex; pthread_cond_t cond; pthread_attr_t attr; int cont; void *func(void*) { printf("func\n"); for(int i = 0; i < 20; i++) { pthread_mutex_lock(&myMutex); cont++; printf("%d\n",cont); if(cont == 10) { printf("signal:\n"); pthread_cond_signal(&cond); // sleep(1); } pthread_mutex_unlock(&myMutex); } printf("Done func\n"); pthread_exit(NULL); } void *anotherFunc(void*) { printf("anotherFunc\n"); pthread_mutex_lock(&myMutex); printf("waiting...\n"); pthread_cond_wait(&cond,&myMutex); cont += 10; printf("slot\n"); pthread_mutex_unlock(&myMutex); printf("mutex unlocked anotherFunc\n"); printf("Done anotherFunc\n"); pthread_exit(NULL); } int main(int argc,char *argv[]) { pthread_t thread; pthread_t anotherThread; pthread_attr_init(&attr); pthread_mutex_init(&myMutex,NULL); pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_JOINABLE); pthread_cond_init(&cond,NULL); pthread_create(&anotherThread,&attr,anotherFunc,NULL); pthread_create(&thread,func,NULL); pthread_join(thread,NULL); pthread_join(anotherThread,NULL); printf("Done MAIN()"); pthread_mutex_destroy(&myMutex); pthread_cond_destroy(&cond); pthread_attr_destroy(&attr); pthread_exit(NULL); return 0; }
很抱歉这篇文章很长,但我是新手,我很乐意学习.你也知道关于Linux上线程和网络的一些好的参考资料或课程/教程吗?我想学习创建一个聊天客户端,我听说我必须知道线程和网络.问题是我不知道如果我学到的东西还不错,因为我不知道我必须知道什么.
非常感谢 :)
解决方法
你的anotherThread只是调用pthread_cond_wait而不先测试是否已经发生了所需的条件(计数器达到10).这是不正确的逻辑,这将导致丢失的唤醒问题:一个反复出现错误的名称,它会困扰错误编写的多线程程序.
条件变量是无状态的.如果在没有线程当前正在等待的条件上调用pthread_cond_signal或pthread_cond_broadcast,则该操作无效.它没有被记住.因此,在另一个线程到达pthread_cond_wait调用之前,您的信令线程可能会非常快速地计数到10,并发出条件变量的信号.
你需要一个围绕pthread_cond_wait的循环.必须检查条件以防它已经为真,这样线程就不会等待已经发生的唤醒.它应该是一个循环,因为唤醒可能是虚假的:只是因为线程通过pthread_cond_wait落下并不意味着条件实际上是真的:
while (cont < 10) pthread_cond_wait(&cond,&myMutex);
此外,不需要创建线程属性只是为了使线程可连接.当您为创建属性使用空指针时,这是默认情况. POSIX线程是可连接的,除非创建分离,或使用pthread_detach转换为分离.
另一件事:尽可能避免在持有互斥锁时调用pthread_cond_signal.这不是不正确的,但它可能是浪费的,因为操作实际上可能必须调用OS内核来唤醒一个线程,因此你在整个系统调用中持有这个昂贵的互斥锁(当你真正需要它时)保护在应用程序中使用共享数据的一些机器指令.