使用上pthread_cond_t遇到的死锁问题 最近在一个项目中使用pthread_cond_t的时遇到一个死锁的问题,特记录分享一下。这个问题的使用场景很简单,客户端程序起两个线程,一个线程发送数据给服务器,另一个线程接收服务器的返回。发送线程向服务器发送一个数据报,然后等待服务器返回(用pthread_cond_t等待),然后继续发送下一个数据包……,如此循环下去。发送代码抽取出来的逻辑像下面这样:
static void* thread_fun_send(void* nouse) { int send_index = 0; while(1) { //模拟发送数据的socket系统调用 printf("send %d\n",send_index++);
//通知接收线程可以接收数据 pthread_mutex_lock(&mutex_send); pthread_cond_signal(&cond_send); pthread_mutex_unlock(&mutex_send);
//等待收到数据的pthread_cond_t pthread_mutex_lock(&mutex_recv); pthread_cond_wait(&cond_recv, &mutex_recv); pthread_mutex_unlock(&mutex_recv); } }
接收线程等待服务器的返回,收到服务器返回后给发送线程发信号(用pthread_cond_t发信号),然后继续等待接收服务器下一个返回……,如此循环下去。接收代码抽取出来的逻辑像下面这样: static void* thread_fun_recv(void* nouse) { int recv_index = 0; while(1) { //等待收到数据的pthread_cond_t,模拟阻塞的socket pthread_mutex_lock(&mutex_send); pthread_cond_wait(&cond_send, &mutex_send); pthread_mutex_unlock(&mutex_send);
//模拟接收数据的socket系统调用 printf("recv %d\n",recv_index++);
//通知发送线程数据已经收到 pthread_mutex_lock(&mutex_recv); pthread_cond_signal(&cond_recv); pthread_mutex_unlock(&mutex_recv); } } 就这么一个简单的应用场景,看起来好像是很合乎逻辑的,但在实际的运行中会出现死锁的问题。经过综合分析后发现其实是在理解pthread_cond_t上不准确了,一开始会认为它和windows中的Event是一样的,只是调用的API函数名不同而已,其实它们是不同的。且不说自动重置这个功能,在信号的处理上它们也是完全不同的。在Windows中,当Event被置为有信号时,内核会检查有没有在等待这个信号的线程,如果有则唤醒它,如果没有信号会保存起来,下一个等待此信号的线程进来时会直接获得信号而继续运行;但在Linux中, 如果pthread_cond_t被置为有信号时,内核也是会检查有没有在等待这个信号的线程,如果有则唤醒它,但如果没有等待的线程内核则不会保存这个信号(好像这个信号被丢掉了一样),下一个等待信号的线程进来时是不会获得信号而只会进入睡眠的,只有在睡眠后下一次pthread_cond_t被置为有信号时,这个线程才会被唤醒。
点击(此处)折叠或打开
|
|
来自: astrotycoon > 《thread》