[英]std::future: Async single producer + any number of consumers problem
我想 model 一個異步操作產生一些T
然后有多個調用在各個線程上獲取該T
的問題。 這些調用將經常重復,因此即使在一個線程上,也會多次請求T
我首先考慮為此使用std::promise
/ std::future
,即
// Declaration
std::promise<T> p;
std::future<T> f = p.get_future();
// Producer code (different function)
p.set_value(...);
// Consumer code (different function; will be called repeatedly from different threads)
return f.get();
這里的問題是, future::get
顯然是一次性操作,不能重復,所以我想到了shared_future::get()
。 但是shared_future
在其文檔中提到:
如果每個線程都通過其自己的 shared_future object 副本進行訪問,則從多個線程訪問相同的共享 state 是安全的。
這看起來很奇怪,因為shared_future
只有 const 方法,它應該始終是線程安全的,所以我認為這個own copy
要求沒有任何必要。 我不知道會有多少線程,所以我不能為每個線程創建一個shared_future
。 消費者代碼可以在任何線程上重復調用。 做這個的最好方式是什么?
每當有人想使用T
時,我可以即時創建一個shared_future
副本嗎? IE:
// Declaration
std::promise<T> p;
std::shared_future<T> f = p.get_future();
// Producer code (different function)
p.set_value(...);
// Consumer code (different function; will be called repeatedly from different threads)
std::shared_future<T> fCopy = f; // Make a private copy of f on the stack.
return fCopy.get(); // Use the copy to get the T
這是應該怎么做的嗎? 復制構造shared_future
線程安全嗎? 這會有很好的表現,還是我應該做不同的事情?
為我在評論回復中的錯誤建議道歉,但我認為你想要的是std::latch
。 初始化為 1,並且有任何等待它的東西調用wait()
方法永遠等待直到它完成,或者try_wait()
如果你不想永遠等待。
這就是我來自的地方:
int main(int argc, char* argv[])
{
std::latch mylatch{ 1 };
std::unique_ptr<int> common_source{};
std::mutex sync_cout{};
auto myTester = [&]() {
mylatch.wait();
std::lock_guard locker{ sync_cout };
cout << "Through the latch, value is: " << *common_source << endl;
};
// Start the waiting threads
std::vector<std::thread> threads;
for (int i = 0; i < 5; i++)
{
std::thread mythread{ myTester };
threads.push_back(std::move(mythread));
}
cout << "Threads started" << endl;
common_source = std::make_unique<int>(15);
mylatch.count_down();
std::this_thread::sleep_for(100ms);
{
std::lock_guard locker{ sync_cout };
cout << "After count_down, starting a fresh thread to show it is let through" << endl;
}
{
std::thread mythread{ myTester };
threads.push_back(std::move(mythread));
}
// Wait for the threads to finish
for (auto& curThread : threads)
{
curThread.join();
}
cout << "All threads down" << endl;
}
適應你認為合適的。 將unique_ptr
更改為您要分發的任何類型,並顯然鎖定以復制它,而不僅僅是輸出一個數字。 如果由於某種原因“處理程序”遲到(在它已經倒計時之后),它只是讓通過,就像你想要的那樣,而不是像我在我的例子中展示的那樣永遠等待。
By default, any function defined in the C++ standard library is considered to be thread-safe relative to some object if that function takes that object by pointer/reference to a const
object. shared_future
有一個復制構造函數,它通過const
獲取引用。 因此,shared_future 的復制構造函數相對於從中復制它的shared_future
是線程安全的,只要shared_future
shared_future
的所有其他操作也是線程安全的。
因此,只要您不對shared_future
實例執行任何線程不安全的操作,您就可以從任何線程制作該實例的本地副本。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.