[英]Thread-safe and unique execution of nested function
我有一個MyClass
類,其函數A
並行執行多次。 然后,有一個功能B
只能執行一次。 我的初始設置看起來很簡單,但是我懷疑它是線程安全的。 如何使其成為線程安全的? 我正在使用C ++ 11。
class MyClass {
public:
void A() {
static bool execute_B = true;
if (execute_B) {
execute_B = false;
B();
}
}
private:
void B() {
std::cout << "only execute this once\n";
}
};
這是std::atomic_flag
的主要用例:
class MyClass {
public:
void A() {
if (!execute_B_.test_and_set()) {
B();
}
}
private:
void B() {
std::cout << "only execute this once\n";
}
std::atomic_flag execute_B_ = ATOMIC_FLAG_INIT;
};
請注意,任何涉及static
解決方案都只允許一次MyClass::B
調用,即使在多個MyClass
實例之間也是如此,這可能對您沒有意義; 假設這沒有意義,則此方法允許每個 MyClass
實例一次調用MyClass::B
是的,您的代碼不是安全的:多個線程可以在execute_B
設置為false之前的if
語句內輸入。 另外, execute_B
也不是原子的,因此線程之間更改的可見性可能會有問題。
有很多方法可以使其成為線程安全的。 請注意,版本(1),(2)和(4)將阻止其他線程在B
執行點之后執行A
,直到B
執行完成。
1)已經提到過std::call_once
:
void A() {
static std::once_flag execute_B;
std::call_once(flag1, [this](){ B(); });
}
2)調用B
作為初始化靜態變量的結果:
void A() {
static bool dummy = [this](){ B(); return true; });
}
3)使用原子交換:
void A() {
static std::atomic<bool> execute_B = true;
if(execute_B.exchange(false, std::memory_order_acq_rel))
B();
}
4)用互斥鎖保護檢查(為避免以后性能下降,請使用雙重檢查鎖定):
void A() {
static std::mutex m_;
static std::atomic<bool> execute_B = true;
if(execute_B.load(std::memory_order_acquire)) {
std::unique_lock<std::mutex> lk(m_);
if(execute_B.load(std::memory_order_relaxed)) {
B();
execute_B.store(false, std::memory_order_release);
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.