2013-10-02 70 views
6

假設我有兩個線程和一個共享C++ 11條件變量。 如果thread1調用notify並在那個thread2調用等待之後會發生什麼? 將永久thread2塊,否則它將繼續它的工作由於thread1的通知調用?如果我呼叫等待通知條件變量,會發生什麼

編輯:

enum bcLockOperation 
{ 
    bcLockOperation_Light = -1, 
    bcLockOperation_Medium = 50, 
    bcLockOperation_Heavy = 1 
} 
class BC_COREDLL_EXP bcCustomMutex 
     { 
     private: 
      bcCustomMutex(const bcCustomMutex&); 
      bcCustomMutex& operator=(const bcCustomMutex&); 

    protected: 
     bcAtomic<int> mFlag; 
     bcMutex mMutex; 
        bcConditionVariable mCond; 

    public: 
     bcCustomMutex() { bcAtomicOperation::bcAtomicInit(mFlag, 0); }; 
     ~bcCustomMutex() {}; 

     /*bcMutex(const bcMutex& pOther) = delete; 
     bcMutex& operator=(const bcMutex& pOther) = delete;*/ 

     bcInline void lock(bcLockOperation pLockOperation = bcLockOperation_Medium) 
     { 
      bcINT32 lNewLoopCount = static_cast<bcINT32>(pLockOperation); 
      bcINT32 lLoopCounter = 0; 
      bcINT32 lExpected = 0; 
      bcINT32 lLoopCount = bcAtomicOperation::bcAtomicLoad(mFlag, bcMemoryOrder_Relaxed); 

      while (true) 
      { 
       while(bcAtomicOperation::bcAtomicLoad(mFlag, bcMemoryOrder_Relaxed) != 0 && 
         lLoopCounter != lLoopCount) 
        ++lLoopCounter; 
       bcAtomicOperation::bcAtomicCompareExchangeStrong(
        mFlag, 
        &lExpected, 
        lNewLoopCount, 
        bcMemoryOrder_Acquire, 
        bcMemoryOrder_Relaxed); 
       if(lExpected == 0) 
       { 
        //mMutex.lock(); 
        return; 
       } 
       else if(lLoopCounter == lLoopCount) 
       { 
        bcLockGuard<bcMutex> lGuard(mMutex); 
              mCond.wait(mMutex); 

       } 
       else 
        continue; 
      } 
     }; 
     bcInline void UnLock() 
     { 
      bcAtomicOperation::bcAtomicStore(mFlag, 0, bcMemoryOrder_Relaxed); 
      bcUniqueLock<bcMutex> lGuard(mMutex); 
          mCond.notifyOne(); 
     }; 
     bcInline bcBOOL TryLock() 
     { 
     }; 
    }; 

我想寫一個自定義的互斥使得每個線程都可以提供表示操作的當前線程要執行復雜的參數。 如果操作的複雜度較低,其他線程將像循環鎖一樣處於循環狀態,但如果操作的複雜度爲中等,則每個線程將迭代50次,然後通過條件變量休眠,如果操作非常複雜,則其他線程會直接睡覺。

現在假設線程1個鎖定這個互斥及線程無二由於等待其循環計數器達到其最終和右鎖定條件變量的互斥體之前,線程1調用條件變量通知。現在thread2會睡眠,直到另一個線程鎖定自定義互斥鎖,然後調用它解鎖。

我新的多線程和我想學習。我知道我的類可能包含錯誤或者可能是完全錯誤的,但是有什麼方法可以糾正這個問題或者寫一個這樣的互斥體的好算法。

另一個問題是:是我的原子操作正確排序?

+2

你可以自己嘗試,對吧? –

+0

是的,你是對的!但我的筆記本電腦有問題,我正在修理它。現在我正在考慮我的問題,直到我可以編寫代碼。對不起 – MRB

+0

沒有「通知條件變量」這樣的事情。瞭解條件變量最重要的是它們是無狀態的。 –

回答

13

線程2將阻塞,直到有人呼叫通知。調用通知在調用時正在等待的發佈線程。如果沒有線程在等待,他們什麼也不做。他們沒有保存。

+3

請注意,這是事件在Windows w.r.t「SetEvent」和「ResetEvent」上的工作方式* *相反的行爲。 –

10

通常都認爲決定等待代碼和決定通知共享相同的互斥代碼。所以thread2永遠不會「錯過」來自thread1的通知。

這裏是典型的基於鎖的併發隊列例如:

void push(int x) 
{ 
    lock_guard<mutex> guard{queue_mutex}; 
    thequeue.push(x); 
    not_empty_condition.notify_one(); 
} 

int pop() 
{ 
    unique_lock<mutex> guard{queue_mutex}; 
    not_empty_condition.wait(guard, []{ return !thequeue.empty(); }); 
    int x = thequeue.front(); 
    thequeue.pop(); 
    return x; 
} 

假設線程1和線程分別運行push()pop()。一次只有其中一個會在關鍵部分。

  • 如果線程2有鎖,要麼永遠等待,因爲隊列不爲空(所以「丟失」一個通知是無害的),或坐在那裏等待通知(這不會丟失) 。

  • 如果線程1拿到了鎖,它將把一個元素在隊列中;如果線程2正在等待,它會得到正確的通知;如果線程2仍在等待互斥鎖,它將永遠不會等待,因爲隊列中至少有一個元素,所以失去通知是無害的。

以這種方式,只有在不需要首先通知時纔會丟失通知。

現在,如果你有一點條件變量,其中「失去」的通知有什麼後果不同的使用,我相信你要麼有一個競爭條件,或者乾脆是使用了錯誤的工具。

+0

你能看看我的編輯嗎?謝謝。 – MRB

+0

如果你想問一個新問題,發佈一個新問題,不要編輯你的舊問題來改變/添加不相關的東西。另外,我可以不讀bcRead lBadly縮進bAND l有意pObfuscated bcCode。 – DanielKO

相關問題