结束可能已加入或取消引用的主题

时间:2017-10-23 14:18:42

标签: multithreading pthreads

我在决定在这种情况下做什么时遇到问题,我希望有一个分离的线程,但仍然可以加入它以防我想提前中止它,大概是在开始一个新实例之前它,以确保我不会让线程仍然访问它不应该的东西。

这意味着我不应该在调用之后立即拆分线程,所以我有几个选择:

  • 当线程到达执行结束时自行分离,但如果我尝试从主线程加入线程,则不会导致问题?如果在自我分离之后尝试加入它的问题可以解决,那么这将是我的首选解决方案。我可以在自解析之前取消引用主线程可以从自分离线程访问的线程句柄,但是如果主线程在解除引用句柄之前尝试加入并且线程自分离,则可能导致问题,所以我必须保护线程中的解除引用,但是(我不知道如何,我可能需要创建一个变量来表明这一点)我会检查是否应该加入主线程中互斥体,使事情复杂化。不知怎的,我觉得这不是正确的做法。
  • 让线程一直悬挂,直到我最终加入它,这可能需要很长时间才能发生,这取决于我在摆脱它所做的事情之前组织的事情(例如在释放图像之前加入线程)当我不再需要它时由线程加载/处理了)
  • 定期主线程轮询以了解线程何时完成其工作,然后加入(或实际分离)并指示不再尝试加入它?
  • 或者我应该从线程中调用pthread_exit(),但如果我尝试加入它会怎么样?

如果我听起来有点困惑,因为我是。我使用TinyCThread在C99中编写,这是pthread和Win32 API线程的简单包装器。我甚至不确定如何取消引用我的线程句柄,在Windows上,线程句柄是HANDLE,并且将句柄设置为NULL似乎是这样做的,我不确定是什么使用pthread_t类型执行此操作的正确方法。

结语:基于John Bollinger的答案,我选择了分离主题,将大部分主题代码放入互斥锁中,这样如果任何其他线程想要阻塞,直到线程实际完成,它可以使用该互斥锁。

2 个答案:

答案 0 :(得分:1)

使用抽象层(如TinyCThreads)的代价是,您只能依赖抽象的已定义特征。 Windows和POSIX都提供了不一定由TinyCThreads反映的功能和细节。另一方面,这可能会迫使您依靠更坚实的基础,而不是在特定于实现的功能的帮助下进行攻击。

无论如何,你说,

  

我希望有一个分离的主题,但仍然能够加入它以防我想提前中止它,

但这不一致。分离线程后,您无法加入它。我怀疑你的意思更像是,"我想要一个我可以加入的帖子,只要它正在运行,但是当它终止时我不必加入。"这至少是一致的,但它侧重于机制。

我认为你实际上想要的会更好地描述为一个线程,只要它正在运行就可以同步取消,但是当它终止时你不需要加入。然而,我注意到,整个想法预设了一种使线程尽早终止的方法,并且看起来TinyCThread似乎没有为此提供任何内置工具。它还需要一种机制来确定给定的线程是否仍然存在,而TinyCThread也没有提供这种机制。

首先,您需要一些额外的每线程共享状态来跟踪线程状态(运行/中止请求/终止)。因为状态是共享的,所以你需要一个互斥锁来保护它,这也许需要每个线程。此外,为了使一个线程(例如主线程)在取消线程时等待该状态改变,它将需要一个每线程条件变量。

有了这个,新线程可以自行分离,但它必须定期检查是否已请求中止。当线程结束其工作时,无论是因为它发现了已经请求中止还是因为它到达其工作的正常结束,它执行任何所需的清理,将状态设置为"终止",广播到CV ,并退出。

任何想要取消另一个的线程都会锁定相关的互斥锁,并检查线程是否已经终止。如果没有,它将线程状态设置为"中止请求",并等待条件变量,直到状态变为"终止"。如果需要,您可以使用定时等待来允许取消请求超时。成功取消线程后,可以清除互斥锁,cv和共享变量。

我注意到所有这一切都取决于我对您的请求的解释,特别是您所追求的是中止/取消线程的前景。您提出的替代方案似乎都没有解决这个问题;在大多数情况下,他们放弃不需要的线程,这不符合您表达的兴趣,阻止它对共享状态进行不必要的更改。

答案 1 :(得分:0)

我不清楚你想要什么,但你可以使用一个条件变量来实现线程的基本任意连接语义。 POSIX Rationale包含了一个示例,展示了如何通过超时实现pthread_join(搜索timed_thread)。