簡體   English   中英

刪除std :: lock_guard相對於其他堆棧分配對象的順序/速度?

[英]delete order/speed of std::lock_guard relative to other stack-allocated objects?

據我所知,在lock_guard被刪除與函數(在另一個線程中運行)實際返回之間有相當長的時間。 請參閱下面的TEST(...)評論

bool bDone = false;
void  run_worker(Foo* f) {
  f->Compute();
  bDone = true;
}

TEST(FooTest,ThreadFoo) {
   Foo* f = makeFoo();
   std::thread  worker( run_worker, f );
   worker.detach();
   micro_wait(100); // wait for N microseconds

   f->Reset(); // should block until Compute() is done

   // !!?? Why is this necessary !?!? 
   int k=0;
   while(++k<500 && !bDone)
     micro_wait(100);**   

   EXPECT_TRUE(bDone); // Fails even with a single micro_wait(100)!     
}

對於何時/為什么在f-> Compute()完成和設置bDone之間會有這樣的時間間隔,是否有很好的解釋? 我的懷疑是,互斥鎖會被解鎖,而仍有許多工作需要清理,以清除Compute()中分配的基於堆棧的變量,但這純粹是一種假設。

以下是用於計算和重置的存根:

void Foo::Compute() {
  std::lock_guard<std::mutex>  guard(m_Mutex);
  // ... allocate bunch of temporary stuff on stack, update *this
}

void Foo::Reset() {
  std::lock_guard<std::mutex>  guard(m_Mutex);
  // ... simpler stuff, clear
}

bDone沒有同步。

bDone的值為false時,編譯器很有可能將bDone加載到寄存器中,然后繼續使用寄存器緩存的版本,而不是從內存中獲取更新的版本。 或者,您的指令可能會重新排序,以便釋放鎖定后將 bDone設置為false。

解決此問題的正確方法是使用std::atomic<bool> 輔助線程可以通過調用bDone.store(true)對其進行更新,而等待線程可以通過調用bDone.load()讀取其最新值。

如果您想讀入內存順序以幫助理解為什么需要原子,則可以通過使用acquirerelease順序來進一步改進此功能(盡管對於單元測試來說,這並不重要)。

除此之外,您真正應該做的是加入工作線程。 直到線程結束,聯接才會阻塞,因此可以確保您的Compute函數已完成執行。 如果您擔心它可能永遠運行(或運行時間太長),建議使用boost::thread而不是std::thread ,因為它提供了timed_join函數,該函數在指定時間段后不再等待線程時間。

暫無
暫無

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

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