为什么我要启动一个“暂停”的线程?

时间:2010-07-01 10:17:21

标签: c++ c multithreading

Windows和Solaris线程API都允许以“挂起”状态创建线程。线程实际上只在以后“恢复”时启动。我已经习惯了没有这个概念的POSIX线程,而且我很难理解它的动机。任何人都可以建议为什么创建一个“暂停”的线程会有用吗?

这是一个简单的说明性示例。 WinAPI允许我这样做:

t = CreateThread(NULL,0,func,NULL,CREATE_SUSPENDED,NULL);
// A. Thread not running, so do... something here?
ResumeThread(t);
// B. Thread running, so do something else.

(更简单的)POSIX等价物似乎是:

// A. Thread not running, so do... something here?
pthread_create(&t,NULL,func,NULL);
// B. Thread running, so do something else.

有没有人有任何现实世界的例子,他们能够在A点(在CreateThread和ResumeThread之间)做一些事情,这在POSIX上很难?

6 个答案:

答案 0 :(得分:22)

  1. 要预先分配资源,然后几乎立即启动该线程。
  2. 您有一种重用线程的机制(恢复它),但您实际上没有要重用的线程,您必须创建一个。

答案 1 :(得分:9)

在很多实例中创建一个处于挂起状态的线程很有用(我发现) - 您可能希望获得该线程的句柄并设置其中的一些属性,然后再允许它开始使用您所拥有的资源设置它。

暂停开始比启动它更安全然后暂停它 - 你不知道它有多远或它正在做什么。

另一个示例可能是当您想要使用线程池时 - 您预先创建必要的线程,暂停,然后在请求进入时,选择其中一个线程,设置任务的线程信息,以及然后将其设置为可调度。

我敢说有很多方法可以不使用CREATE_SUSPENDED,但它确实有其用途。

如果您需要大量详细信息,可以在“通过C / C ++的Windows”(Richter / Nasarre)中使用一些示例!

答案 2 :(得分:4)

CreateThread中存在隐式争用条件:在线程开始运行之后之前,您无法获取线程ID。当调用返回时,它完全不可预测,因为您知道线程可能已经完成。如果该线程在该进程的其余部分中导致需要TID的任何交互,那么您就遇到了问题。

如果API不支持启动线程暂停,这不是一个无法解决的问题,只需立即在互斥锁上使用线程块,并在CreateThread调用返回后释放该互斥锁。

但是,如果缺少API支持,Windows API中的CREATE_SUSPENDED会另外使用 非常难以处理。 CreateProcess()调用也接受此标志,它暂停进程的启动线程。机制是相同的,进程被加载,你将得到一个PID但没有代码运行,直到你释放启动线程。这非常有用,我使用此功能来设置一个过程保护,检测过程失败并创建一个小型转储。 CREATE_SUSPEND标志允许我检测并处理初始化失败,通常很难排除故障。

答案 3 :(得分:3)

您可能希望启动具有其他(通常较低)优先级或具有特定关联掩码的线程。如果你像往常一样生成它,它可以在一段时间内以不受欢迎的优先级/亲和力运行。所以你开始它暂停,改变你想要的参数,然后恢复线程。

答案 4 :(得分:3)

我们使用的线程能够交换消息,我们有连接这些线程的任意可配置的优先级继承消息队列(在配置文件中描述)。在构建每个队列并连接到每个线程之前,我们不能允许线程执行,因为它们将开始向无处发送消息并期望响应。在构建每个线程之前,我们无法构造队列,因为它们需要附加到某些东西上。因此,在配置最后一个线程之前,不允许任何线程工作。我们使用boost.threads,他们做的第一件事就是等待boost::barrier

答案 5 :(得分:1)

我曾经偶然发现类似的问题。暂停初始状态的原因在其他答案中处理。

我使用pthread的解决方案是使用互斥锁和cond_wait,但我不知道它是否是一个好的解决方案,是否可以满足所有可能的需求。此外,我不知道线程是否可以被认为是暂停的(当时,我认为手册中的“阻止”是一个synonim,但可能不是这样)