簡體   English   中英

確保線程沒有鎖定互斥鎖兩次?

[英]Ensure that a thread doesn't lock a mutex twice?

假設我在下面的示例中有一個運行runController之類的成員方法的線程:

class SomeClass {
public:
    SomeClass() { 
         // Start controller thread
         mControllerThread = std::thread(&SomeClass::runController, this) 
    }

    ~SomeClass() {
         // Stop controller thread
         mIsControllerThreadInterrupted = true;
         // wait for thread to die.
         std::unique_lock<std:::mutex> lk(mControllerThreadAlive); 
    }

    // Both controller and external client threads might call this
    void modifyObject() {
         std::unique_lock<std::mutex> lock(mObjectMutex);
         mObject.doSomeModification();
    }
    //...
private:
    std::mutex mObjectMutex;
    Object mObject;

    std::thread mControllerThread;
    std::atomic<bool> mIsControllerInterrupted;
    std::mutex mControllerThreadAlive;

    void runController() {        
        std::unique_lock<std::mutex> aliveLock(mControllerThreadAlive);
        while(!mIsControllerInterruped) {
            // Say I need to synchronize on mObject for all of these calls
            std::unique_lock<std::mutex> lock(mObjectMutex);
            someMethodA();
            modifyObject(); // but calling modifyObject will then lock mutex twice
            someMethodC();
        }
    }
    //...
};

並且runController一些(或所有)子例程需要修改線程之間共享並由互斥鎖保護的數據。 其中一些(或全部)也可能被需要修改此共享數據的其他線程調用。

有了C ++ 11的所有榮耀,我怎樣才能確保沒有線程曾經兩次鎖定互斥鎖?

現在,我將unique_lock引用作為參數傳遞給方法,如下所示。 但這似乎很笨重,難以維護,可能是災難性的......等等......

void modifyObject(std::unique_lock<std::mutex>& objectLock) {

    // We don't even know if this lock manages the right mutex... 
    // so let's waste some time checking that.
    if(objectLock.mutex() != &mObjectMutex)
         throw std::logic_error();

    // Lock mutex if not locked by this thread
    bool wasObjectLockOwned = objectLock.owns_lock();
    if(!wasObjectLockOwned)
        objectLock.lock();

    mObject.doSomeModification();

    // restore previous lock state
    if(!wasObjectLockOwned)
        objectLock.unlock();

}

謝謝!

有幾種方法可以避免這種編程錯誤。 我建議在類設計級別上進行:

  • 公共私人成員職能分開,
  • 只有公共成員函數鎖定互斥鎖
  • 其他成員函數從不調用公共成員函數。

如果內部和外部都需要函數,則創建函數的兩個變體,並從一個變為另一個:

public:
    // intended to be used from the outside
    int foobar(int x, int y)
    {
         std::unique_lock<std::mutex> lock(mControllerThreadAlive);
         return _foobar(x, y);
    }
private:
    // intended to be used from other (public or private) member functions
    int _foobar(int x, int y)
    {
        // ... code that requires locking
    }

暫無
暫無

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

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