简体   繁体   English

ThreadPool,Function局部变量和Thread局部存储

[英]ThreadPool, Function local variables and Thread local storage

In thread pool, threads are reused to avoid thread creation and destruction.在线程池中,线程被复用,避免了线程的创建和销毁。 When the thread pool reuses a thread, it does not clear the data in thread local storage.线程池在重用一个线程时,不会清除线程本地存储中的数据。 Hence, when a method examines thread local storage, the values it finds are left over from an earlier use of the thread pool thread.因此,当方法检查线程本地存储时,它找到的值是先前使用线程池线程遗留下来的。

Function local variables are local to function and not to threads. Function 局部变量对于 function 是局部的,而不是线程。 But when i created a thread pool using boost::asio::thread_pool, the memory for local variables created inside function share the same memory for the same thread.但是,当我使用 boost::asio::thread_pool 创建线程池时,在 function 内部创建的局部变量的 memory 与同一线程共享相同的 memory。

Hence, I have few questions...因此,我几乎没有问题......

  1. Are function local variables stored inside thread local storage.是 function 局部变量存储在线程本地存储中。 And is it because of that i am getting same memory for the same threads?是因为我在相同的线程上得到相同的 memory 吗?
  2. The same question for function parameters which are passed by value?对于按值传递的 function 参数,同样的问题?
  3. Is there any way to clear the thread local storage before reusing the threads?在重用线程之前有没有办法清除线程本地存储?

Program程序

#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/asio/thread_pool.hpp>
#include <BoostThreading/UtilBoost.hpp>
#include <iostream>
boost::mutex mutex;
void my_task(int g)
{
    boost::lock_guard<boost::mutex> lock(mutex);
    int i=0;
    i++;
    std::cout<<boost::this_thread::get_id()<<" "<<&i<<" "<<i<<" "<<&g<<" "<<g<<"\n";
    SleepMs(30);
}
int main()
{
    boost::asio::thread_pool pool(4);
    for(int i=0;i<10;i++)
        boost::asio::post(pool, boost::bind(my_task,i));
    pool.join();
}

Output Output 在这里输出图像

First is the thread id, second is the address for variable i created inside the function and third address is the address for variable g passed to my_task by pass by value.第一个是线程 ID,第二个是我在 function 中创建的变量的地址,第三个地址是通过值传递传递给 my_task 的变量 g 的地址。

  1. Are function local variables stored inside thread local storage.是 function 局部变量存储在线程本地存储中。 And is it because of that i am getting same memory for the same threads?是因为我在相同的线程上得到相同的 memory 吗?

Function local variables live on the stack. Function 个局部变量存在于堆栈中。

The stack is defacto always (implicitly) thread-local.堆栈实际上总是(隐含地)线程本地的。 That's a direct result of CPU design.这是 CPU 设计的直接结果。

Only exceptions might be when context switching libraries such as Boost Context (eg implementing stackful coroutines or fibers).唯一的例外可能是上下文切换库,例如 Boost Context(例如,实现堆栈协程或纤程)。

Read this absolutely awesome answer to understand stack allocation and stack reuse: Can a local variable's memory be accessed outside its scope?阅读这个绝对棒的答案以了解堆栈分配和堆栈重用: Can a local variable's memory be accessed outside its scope?

  1. The same question for function parameters which are passed by value?对于按值传递的 function 参数,同样的问题?

Same answer.同样的答案。

  1. Is there any way to clear the thread local storage before reusing the threads?在重用线程之前有没有办法清除线程本地存储?

That's actually an interesting question.这实际上是一个有趣的问题。 It generalizes to "is there a secure-erase allocator in C++ that includes objects with automatic storage duration?".它概括为“C++ 中是否有一个包含具有自动存储持续时间的对象的安全擦除分配器?”。

No that doesn't exist.不,那不存在。 It can be approximated , but it will involve wrapping all your primitive types into non-trivial types.它可以被近似,但它将涉及将所有原始类型包装成非平凡类型。 It may be more effective to actively wipe the stack down with an explicit function at the end of a task.在任务结束时使用明确的 function 主动清除堆栈可能会更有效。

The upper frames will have to remain in-tact because they may (and will) contain information required for proper thread management (eg if you use boost::thread it will contain the structures that allow thread interruption, portable emulation of thread-local storage with boost::thread_specific_ptr etc.)上层框架必须保持完整,因为它们可能(并且将)包含正确线程管理所需的信息(例如,如果您使用boost::thread它将包含允许线程中断的结构,线程本地存储的可移植仿真使用boost::thread_specific_ptr等)

If you need anything like this, look for an existing library around "secure erase" because it's very very easy to get wrong.如果您需要这样的东西,请寻找围绕“安全擦除”的现有库,因为它很容易出错。 Eg a naive memset call can (and will) often be optimized away by the compiler.例如,一个简单的memset调用可以(并且将会)经常被编译器优化掉。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM