pthread条件变量

时间:2009-02-08 09:54:55

标签: pthreads

我正在实现一个包含任务队列的线程。第一个任务添加到队列后,线程就会开始运行它。

我应该使用pthread条件变量来唤醒线程还是有更合适的机制?

如果我在pthread_cond_signal()没有阻止其他线程时调用pthread_cond_wait()而是做某事,会发生什么?信号会丢失吗?

5 个答案:

答案 0 :(得分:12)

如果您的队列已经是线程安全的,那么信号量是唯一的。也, 一些信号量实现可能受到最高计数器值的限制。 即使你不太可能超过最大值。

最简单,最正确的方法如下:

pthread_mutex_t queue_lock;
pthread_cond_t  not_empty;
queue_t queue;

push()
{
  pthread_mutex_lock(&queue_lock);
  queue.insert(new_job);
  pthread_cond_signal(&not_empty)
  pthread_mutex_unlock(&queue_lock);
}
pop()
{
  pthread_mutex_lock(&queue_lock);
  if(queue.empty()) 
     pthread_cond_wait(&queue_lock,&not_empty);
  job=quque.pop();
  pthread_mutex_unlock(&queue_lock);
}

答案 1 :(得分:11)

来自pthread_cond_signal Manual

  

如果cond上当前没有线程被阻止,pthread_cond_broadcast()和pthread_cond_signal()函数将无效。

我建议你使用Semaphores。基本上,每次在队列中插入任务时,都会“提升”信号量。工作线程通过“向下”来阻塞信号量。由于每个任务都会“up”一次,所以只要队列中有任务,工作线程就会继续运行。当队列为空时,信号量为0,工作线程阻塞,直到新任务到达。当工作人员忙碌时,当超过1个任务到达时,信号量也很容易处理。请注意,您仍然必须锁定对队列的访问以保持插入/删除原子。

答案 2 :(得分:1)

信号将丢失,但您希望在这种情况下信号丢失。如果没有线程被唤醒,则该信号没有用处。 (如果没有人在等待什么,发生时不需要通知任何人,对吗?)

对于条件变量,丢失的信号不会导致线程“在火中睡觉”。除非您实际编写一个线程以便在已经发生火灾时进入休眠状态,否则无需“保存信号”。当火灾开始时,您的广播将唤醒任何睡眠线程。当你已经发生火灾时,你必须非常愚蠢地编写一个线程来进入睡眠状态。

答案 3 :(得分:0)

如前所述,信号量应该是最佳选择。如果你需要一个固定大小的队列,只需使用2个信号量(如经典的生产者 - 消费者)。

在artyom代码中,最好用pop()函数中的“while”替换“if”来处理虚假唤醒。

答案 4 :(得分:0)

没有效果。

如果检查pthread_condt_signal是如何实现的,condt会使用几个计数器来检查是否有任何等待线程被唤醒。例如,glibc-nptl

 /* Are there any waiters to be woken?  */
 if (cond->__data.__total_seq > cond->__data.__wakeup_seq){
    ...
 }