【问题标题】:pthread_cond_signal from multiple threads来自多个线程的 pthread_cond_signal
【发布时间】:2015-03-27 07:19:35
【问题描述】:

假设有一个线程调用pthread_cond_wait 并等待信号:

   pthread_mutex_lock(&m);
         .....
   while(run) 
   {
      do {
        pthread_cond_wait(&cond,&m);
      } while(!got_signal);
      got_signal = false;
      do_something();
   }

并且有多个线程应该传递信号:

pthread_mutex_lock(&m);
got_signal = true;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&m);

这个解决方案足够安全吗?如果多个线程发送信号会发生什么? mmutex 是否足以保证所有信号都被序列化并且不会丢失?

【问题讨论】:

  • 你的循环坏了,调用pthread_cond_wait,即使got_signal已经是真的了。另外,你的问题没有意义。 “所有信号”是什么意思?听起来您对条件变量的工作方式有一些相当大的误解。条件变量是无状态的——如果你有可以有状态的信号,你的代码必须实现那个状态。

标签: c multithreading pthreads posix


【解决方案1】:

在您发布的代码中,允许线程调用pthread_cond_signal() 的唯一地方是它们可以获取m,并且只有当您的等待线程在pthread_cond_wait() 上被阻塞时才会发生这种情况。

但是,在等待线程被唤醒并可以获取互斥锁之前,两个信号线程可能会在彼此之后获取互斥锁。在这种情况下,您将丢失第二个信号(以及在此之后,在等待线程运行之前可能到达的任何其他信号),因为您的等待线程只能“看到”它已发出信号,但看不到它有多少次发生了。

为确保您不会丢失任何信号,您可以使用计数器而不是 got_signal 标志:

等待线程:

pthread_mutex_lock(&m);
     .....
while(run) 
{
   while(signal_count == 0) {
     pthread_cond_wait(&cond,&m);
   } 
   --signal_count;
   do_something();
}

信号线程:

pthread_mutex_lock(&m);
++signal_count;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&m);

(另请注意,我已将 do...whileloop 与 while 循环交换,以确保在仍有未处理的信号时不会调用 pthread_cond_wait()。)

现在,如果多个线程最终彼此直接发出信号,signal_count 将变得不止一个,这将导致等待线程多次运行其do_something() 而不仅仅是一次。

【讨论】:

  • 如果我的内存区域包含应该通过信号传递给处理程序线程的数据,我该怎么办?我需要另一个互斥体,对吗?
  • @olegst 我不完全确定你的意思。但是,如果您想将数据从信号线程传递到等待线程,则需要某种方法来确保该数据不会因多个线程同时访问而导致不一致(与所有其他数据一样)。在大多数情况下,最简单的方法是确保信令线程不会修改任何已经发送的数据。例如,要么只给等待线程一份数据副本,要么发送一个指向某些数据的指针,并让等待线程在完成后清理该数据。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-12-11
  • 2022-01-01
  • 2020-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多