簡體   English   中英

嵌套函數的線程安全和唯一執行

[英]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.

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