检查线程是不是为增强线程

Posted

技术标签:

【中文标题】检查线程是不是为增强线程【英文标题】:Check if thread is a boost thread检查线程是否为增强线程 【发布时间】:2011-01-24 19:59:56 【问题描述】:

出于线程本地清理的目的,我需要创建一个断言来检查当前线程是否是通过 boost::thread 创建的。我怎样才能检查是否是这种情况?即如何检查当前线程是否被 boost::thread 处理?

我只需要在线程退出时清理线程本地存储。 Boost 的 thread_local_ptr 似乎仅在线程本身是 boost 线程时才有效。

请注意,我不是在清理时进行检查,而是在线程生命周期的某个时候进行。某些函数调用我们的 API/回调之一(间接)导致我分配线程本地存储。只允许 boost 线程执行此操作,因此我需要在那个时候检测该线程是否不是 boost 线程。


有关没有通用清理处理程序的问题,请参阅Destruction of static class members in Thread local storage。我回答了这个问题并意识到 pthread_clenaup_push 实际上不起作用:它不会在线程的干净退出时调用。


虽然我没有检测到 boost 线程的答案,但选择的答案确实解决了我的问题的根源。 Boost thread_specific_ptr 将在任何 pthread 中调用它们的清理。一定是其他原因导致它对我不起作用,因为单独的测试表明它确实有效。

【问题讨论】:

我不认为你真的想要一个 static 断言。在编译时检查静态断言,但要检查运行时是如何创建的还为时过早。我想你只想要一个普通的断言。 我更正了静态断言。 【参考方案1】:

你的问题的前提是错误的:) boost::thread_specific_ptr 即使线程不是 boost 线程也有效。想一想——主线程的线程特定存储如何工作,因为它不可能由 boost 创建?我已经很好地使用了主线程中的 boost::thread_specific_ptr,虽然我没有检查 boost::thread_specific_ptr 的实现,但最明显的实现方式即使对于非 boost 线程也有效。大多数操作系统都允许您获取当前线程的唯一 ID 号,然后您可以将其用作映射/数组/哈希表的索引。

您更有可能遇到其他错误,阻止了您期望看到的行为发生。您应该打开一个单独的问题,其中包含一个说明意外行为的小型可编译代码示例。

【讨论】:

我试图弄清楚它是如何工作的。什么 pthread 函数使这个工作?我正在运行测试,看看是否确实如此。 知道了,对 pthread_key_create 的调用接受一个析构函数。所以这对我来说已经足够好了,但是如果线程不是通过 pthreads 创建的呢? ;) 我实际上是在考虑 pthread_self(),它为您提供当前线程的唯一整数。 pthread_key* 函数可能更有效;我记得在 Linux 的 ELF ABI 中,它们专门支持线程本地存储,这让我认为 CPU 必须以特殊寄存器的形式直接支持它,而 pthread_key_* 可能会利用这些。就好像它不是通过 pthreads 创建的一样——你的孩子,但如果操作系统上有多个线程实现可用,那么它们很可能都减少到同一个核心,所以事情可能会奏效。 关于如何在 Windows 上实现的任何提示? 引用boost.org/doc/libs/1_53_0/doc/html/thread/…:“在某些平台上,不会对使用平台的本机 API 创建的线程执行线程特定数据的清理。”【参考方案2】:

你不能用静态断言来做到这一点:这意味着你可以在编译时检测到它,这是不可能的。

假设您的意思是运行时检查:

如果您不将boost::thread 与其他方法混合使用,那么问题就会消失。任何创建线程的库都应该已经在自动处理它们自己的线程(或者每个关闭函数,您必须调用的 API 文档)。

否则,您可以保留一个包含所有 pthread_ts 的容器,而不是使用 boost::thread,并在关闭时检查线程是否在容器中。如果它不在容器中,则它是使用boost::thread 创建的。

编辑:您是否考虑过设置您的应用程序,以便 API 回调只能发生在使用 boost::thread 创建的线程中,而不是尝试检测它是否是使用 boost::thread 创建的?这样一来,您就可以提前预防问题并消除检查的需要,即使存在,实施起来也会很痛苦。

【讨论】:

抱歉,是的,运行时断言。问题在于从 3rd 方库回调我们的代码。【参考方案3】:

每次 boost 线程结束时,所有 Thread Specific Data 都会被清除。 TSD 是一个指针,在销毁/重置时调用delete p*

可以选择为每个项目调用清理处理程序,而不是delete p*。该处理程序在 TLS 构造函数中指定,您可以使用清理函数进行一次性清理。

#include <iostream>
#include <boost/thread/thread.hpp>
#include <boost/thread/tss.hpp>

void cleanup(int* _ignored) 
    std::cout << "TLS cleanup" << std::endl;


void thread_func() 
    boost::thread_specific_ptr<int> x(cleanup);
    x.reset((int*)1); // Force cleanup to be called on this thread

    std::cout << "Thread begin" << std::endl;


int main(int argc, char** argv) 
    boost::thread::thread t(thread_func);

    t.join();

    return 0;

【讨论】:

问题是,如果线程不是boost::thread,这真的能保证数据的清理吗?

以上是关于检查线程是不是为增强线程的主要内容,如果未能解决你的问题,请参考以下文章

增强线程和信号处理

Redis学习---阿里云Redis多线程性能增强版详解

发送多个同时请求时,单线程异步系统中野兽增强异步 http 客户端的行为

Java多线程:LongAdder 原子操作增强类

Java多线程:LongAdder 原子操作增强类

List的三个子类,泛型,增强for循环