Pthread_join():资源收集器:让多个线程退出

时间:2011-04-13 14:16:42

标签: pthreads

我正在编写并发(多线程)服务器应用程序 - 使用cource的pthread! - 当我遇到pthread_join的问题时,我的应用程序很糟糕(伪代码):

/* Sheduler thread */
while (1) {

   c = get_client();
   r = get_resource();

   communication.c = c;
   communication.r = r;

   pthread_create( clnt_tid, null, clnt_fn, communication);
   resource_alloc_list_add(clnt_tid, r);

}

/* resources Collector thread */
while(!rs_alloc_list_is_empty()) {

   e = get_elt(rs_alloc);
   pthread_join(e.clnt_tid, retour);
   free_rs(e.r);
}
.........

问题是没有非暴力的pthread_join调用 - 有一个但它不可移植 - 并且pthread_join无法在进程编程中加入任何线程,如wait()。因此,如果rsc_collector线程正在等待一个客户端线程退出以获取已分配的资源,并且在此之前所有其他线程都已退出,则其资源将被阻止 - 并且调度程序线程无法为其他客户端提供服务 - 直到第一个线程终止了他的工作。 你能告诉我这个问题的可能解决方案吗?

编辑:

我将更具体,我正在编写本地资源管理系统(lrms)或远程程序执行系统,有三个不同的程序:客户端pg,服务器pg和调度程序pg,客户端联系调度程序和等待调度程序pg为他分配一个空闲服务器,这样他就可以在提交后,在远程服务器上执行他的工作.sched pg将在客户端队列中对客户端地址进行排队。在另一方面,服务器pg向调度程序发送注册消息并等待作业,调度程序将资源队列中的服务器地址排入队列(因此​​我的意思是资源是远程服务器而不是系统分配给该线程的资源)。 调度程序pg由三个主线程组成:

  • main_thread:在Well Known Port绑定的套接字列表。接收和排队需求和注册(换句话说,制作人)
  • scheduler_thread:消费者,解除队列cliets地址获取服务器(出列服务器地址),创建客户端线程,保存客户端/服务器分配。并循环开启。
  • resource_collector thread:等待客户端线程终止以获取已分配的资源。我强调[*]创建一个特定的资源收集线程,因为它对于系统的正确功能非常重要。

注意:

  • 客户端线程获取资源(服务器)的副本而不是原始副本。
  • [*]如果我消除了该线程,并让每个客户端释放其资源(远程服务器地址),那么在某些情况下,当客户端线程在调用free函数之前崩溃时,资源将永远丢失。 ..这就是为什么我不冒险让资源完全由客户线程控制。

2 个答案:

答案 0 :(得分:0)

我建议在退出线程时进行必要的清理,而不是在特殊的收集器线程中。具体来说,使用pthread_key_create()创建的线程局部数据可能会在线程退出时调用相关的析构函数调用。这个析构函数可以释放与线程相关的应用程序资源;最简单的方法是在特定于线程的槽中存储指向资源的指针(参见pthread_set_specific()),在这种情况下,指针将自动发送到析构函数。如果线程一直被创建和销毁,收集器线程仍然可以调用pthread_join();不过,您也可以创建处于分离状态的线程,或者在创建后调用pthread_detach()

另请参阅前面提到的a similar question

答案 1 :(得分:0)

正如alexey先前所说,线程函数可以分配和释放其资源。如果你想要一个可以处理取消的方法,你也可以使用pthread_cleanup_push和pop。

您可以使用全局标志来告诉您线程是否仍处于活动状态。在创建线程之前将其设置为1,并在线程函数退出时将其设置为0。如果你有很多线程,请使用数组。只需测试变量以查看线程是否完成。

希望你的收集器线程不会持续旋转,这会消耗资源。

创建线程很慢。您可能希望永久保留少量线程,让他们从队列中选择要做的工作。当没有工作时,他们应该等待信号。当工作被添加到队列中时,您可以发出想要唤醒的线程信号并再次开始工作。这比为每个工作创建一个线程快1000倍,并在工作完成时销毁线程。