簡體   English   中英

等待線程關閉時提升互斥量拋出錯誤

[英]Boost mutex throw error on close for waiting threads

有沒有辦法讓 boost mutex 在任何等待線程上拋出異常? 我有一個問題,一個對象被刪除了,但對於軟件庫的性質,線程可能仍在對象內的互斥鎖處等待,並且在互斥鎖關閉時拋出一個相當令人討厭的異常。 我想我可以使用多個互斥計數器,但這可能會導致性能下降。 我希望發生的是互斥鎖在關閉時正在等待的任何線程上拋出異常,以便展開堆棧。 有沒有一種干凈的方法來做到這一點,它是獨立於平台的?

這種在銷毀時拋出的互斥鎖的概念似乎無害,但是當需要實現它時,它揭示了您對互斥鎖的思考方式的缺陷。

讓我們看一些示例代碼,以了解這種方法的缺陷。

注:不要使用下面的代碼,它會導致什么,但折磨的無數個小時和痛苦調試同步問題。

class throwing_mutex
{
private:
    mutex m_;
    condition_variable cv_;
    bool destroyed_;
    bool locked_;

public:
    void lock()
    {
        std::unique_lock<std::mutex> lock(m_);
        cv_.wait(lock, [&]() {return !locked_ || destroyed_;}); // Wait until the mutex is unlocked or destroyed.
        if (destroyed_) throw runtime_error("The exception was terminated while waiting.");
        locked_ = true;
    }

    void unlock()
    {
        std::unique_lock<std::mutex> lock(m_);
        locked_ = false;
        lock.unlock();

        cv_.notify_one();
    }

    ~throwing_mutex()
    {
        std::unique_lock<std::mutex> lock(m_);
        destroyed_ = true;
        lock.unlock();

        cv_.notify_all(); // Let all waiters know we are dead.
    }
};

銷毀時,每個等待throwing_mutex都會拋出異常。 但這開辟了一個相當大的競爭條件。

我們已經處理了每個人都在等待互斥鎖的情況——他們會安全地拋出。 我們還沒有處理的情況是有人正在調用lock()但還沒有完全到位。 當他們最終到達可以調用lock()的地步時, throwing_mutex已經被銷毀。 我們剛剛通過有缺陷的方法引入的錯誤稱為use-after-free 如果我們幸運的話,錯誤會很早就清楚地出現,但有時我們就沒有那么幸運了,我們會被折磨數小時或數天。 我們的throwing_mutex類無法解決這個問題,任何需要這樣一個類的代碼都沒有經過深思熟慮的所有權語義。

那么,如果不是通過拋出的互斥鎖,我們如何解決這個問題? 我們修復了互斥鎖和被它鎖定的對象的生命周期。

想必,這是互斥鎖是一個類的成員。 如果是這樣,則意味着延遲銷毀,直到所有依賴該對象的人都完成它為止。 這是通過使用shared_ptr傳達的。 無需深入了解所有權語義的本質,這是最好的答案。 希望我已經改變了你對問題的思考方式,足以讓你偏離原來的計划,轉向更可靠的工作。

暫無
暫無

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

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