簡體   English   中英

ThreadPool,Function局部變量和Thread局部存儲

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

在線程池中,線程被復用,避免了線程的創建和銷毀。 線程池在重用一個線程時,不會清除線程本地存儲中的數據。 因此,當方法檢查線程本地存儲時,它找到的值是先前使用線程池線程遺留下來的。

Function 局部變量對於 function 是局部的,而不是線程。 但是,當我使用 boost::asio::thread_pool 創建線程池時,在 function 內部創建的局部變量的 memory 與同一線程共享相同的 memory。

因此,我幾乎沒有問題......

  1. 是 function 局部變量存儲在線程本地存儲中。 是因為我在相同的線程上得到相同的 memory 嗎?
  2. 對於按值傳遞的 function 參數,同樣的問題?
  3. 在重用線程之前有沒有辦法清除線程本地存儲?

程序

#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 在這里輸出圖像

第一個是線程 ID,第二個是我在 function 中創建的變量的地址,第三個地址是通過值傳遞傳遞給 my_task 的變量 g 的地址。

  1. 是 function 局部變量存儲在線程本地存儲中。 是因為我在相同的線程上得到相同的 memory 嗎?

Function 個局部變量存在於堆棧中。

堆棧實際上總是(隱含地)線程本地的。 這是 CPU 設計的直接結果。

唯一的例外可能是上下文切換庫,例如 Boost Context(例如,實現堆棧協程或纖程)。

閱讀這個絕對棒的答案以了解堆棧分配和堆棧重用: Can a local variable's memory be accessed outside its scope?

  1. 對於按值傳遞的 function 參數,同樣的問題?

同樣的答案。

  1. 在重用線程之前有沒有辦法清除線程本地存儲?

這實際上是一個有趣的問題。 它概括為“C++ 中是否有一個包含具有自動存儲持續時間的對象的安全擦除分配器?”。

不,那不存在。 它可以被近似,但它將涉及將所有原始類型包裝成非平凡類型。 在任務結束時使用明確的 function 主動清除堆棧可能會更有效。

上層框架必須保持完整,因為它們可能(並且將)包含正確線程管理所需的信息(例如,如果您使用boost::thread它將包含允許線程中斷的結構,線程本地存儲的可移植仿真使用boost::thread_specific_ptr等)

如果您需要這樣的東西,請尋找圍繞“安全擦除”的現有庫,因為它很容易出錯。 例如,一個簡單的memset調用可以(並且將會)經常被編譯器優化掉。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM