0

我正在使用 glibc pthreads 库编写一个多线程应用程序。我有 3 个 pthreads - 其中一个称为“调度程序”,另外两个称为“工人”和主线程。主线程监听事件并将它们放入队列中。然后调度程序线程将它们分派到工作队列。工作线程从工作队列中获取事件并执行。问题是有时,事件必须在主线程本身中执行,以防止主要的数据竞争。所以我需要一种机制来在收到特殊事件时暂停主线程并等待所有工作人员完成工作,然后执行此事件。

为了做到这一点,我使用了一个受互斥体保护的整数,其位由工作线程设置和重置。当工作人员在其队列中找不到作业时,它将其位设置为 0。如果有作业,则将其位标记为 1。想法是,如果其中一个工作人员正在运行,则整数为 != 0. 主线程现在,当它想要暂停自己以等待工作人员完成时,现在将进行条件等待,直到整数变为 0。工作线程在重置其位时将检查整数是否变为 0。如果为真,则它将向主线程发出信号。在这一点上,我希望所有的工作人员在他们的队列中都没有工作,所以主线程可以执行特殊事件。由于主线程负责将事件排队到第一个队列,我们​​保证没有事件会潜入工作人员。

伪代码如下。

int pause_threads() => the one called from main thread.  
{  
  pthread_mutex_lock(pause_thread_lock));  

  while (pthread_states != 0) {  
  pthread_cond_wait(pause_mthread_cond), pause_thread_lock));  
  }  

}  

int thread_resume()  => called after the special event is executed by main thread.  
{  
  pthread_mutex_unlock(pause_thread_lock));  
}  

int thread_set_state_wait(index) => index is id 0,1 for each worker  
{  
 pthread_mutex_lock(pause_thread_lock));  
 (thread_states) &= (~(MTHREAD_THR_STATE_RUNNING << index));  
  if (pthread_states == 0)  
     pthread_cond_signal(pause_thread_cond));  
  pthread_mutex_unlock(&(pause_thread_lock));  
}  

 int thread_set_state_running(index)  
{  
   pthread_mutex_lock(pause_thread_lock));  
  (pthread_states) |= (MTHREAD_THR_STATE_RUNNING << index);  
   pthread_mutex_unlock(pause_thread_lock));  

}   

我面临的问题是这段代码并不总是有效。有时,我看到当主线程正在执行特殊事件时,工作线程仍然处于活动状态并正在执行作业。逻辑有什么问题吗?有没有其他可能的方法来实现这一目标?我已尽力寻找解决方案。请帮忙。

4

1 回答 1

0

这是一个棘手的问题。当您的主要例程进入关键部分时,它需要确保:

  1. 调度程序不会再安排任何工作
  2. 工人们完成了他们的工作

这两个都需要其他线程的确认。如果您制作某种消息传递机制或使用预先存在的机制,则将其写成通信问题可能更容易。但是,使用标准的互斥锁和条件变量集,您可能会像这样构造它:

  • 调度器
    1. 安排工作时,增加正在运行的作业(由互斥锁锁定)
  • 工作人员
    1. 完成工作和广播时减少正在进行的作业(由互斥锁锁定)
  • 主要的
    1. 当它需要一个临界区时,它设置一个标志(由互斥锁锁定)一个临界区正在进行中,并在 condvar 上广播该状态已更改
    2. 设置一个标志(也锁定),表明条目正在进行并广播状态更改
    3. 它通过将标志设置为零来等待调度程序确认正在进入的 condvar
    4. 它等待正在运行的工作 condvar 等待工作人员完成
    5. 取消设置正在进行和广播以取消阻塞调度程序
  • 调度器
    1. 在开始工作之前或在 condvar 上检查以查看 main 是否要进入
    2. 取消设置 entry-in-progress 标志并广播以确认
    3. 等待进行中的关键 condvar 以完成 main

当所有这些都准备就绪后,main 可以确保不再安排任何工作,并且所有正在进行的工作都已完成。它可以做它的事情,然后解除对调度程序的阻塞。

于 2013-09-02T07:37:29.387 回答