2013-10-02 6 views
6

2つのスレッドと1つの共有C++ 11条件変数があるとします。 thread1の呼び出しが通知され、その後にthread2の呼び出しが待機する場合はどうなりますか? スレッド2は永遠にブロックされますか、それともthread1による通知の呼び出しのために作業を続行しますか?通知された条件変数でwaitを呼び出すとどうなりますか

編集:

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回反復して条件変数によってスリープし、操作が非常に複雑です直接眠りにつきます。

ここで、thread1はこのmutexをロックし、thread2は条件変数のmutexをロックする前にloopCounterがその最後と右に到達するのを待っているため、thread1は条件変数に対してnotifyを呼び出します。他のスレッドがカスタムミューテックスをロックしてからロックを呼び出すまで、thread2はスリープします。

私はマルチスレッド化に新しいので、私は学びたいと思っています。私のクラスにはエラーが入っているかもしれないし、まったく間違っているかも知れませんが、このようなミューテックスを書くためにこの問題や正しいアルゴリズムを修正する方法はあります。

もう1つの質問:アトミック操作が正しく注文されていますか?

+2

あなたはそれを自分で試すことができますか? –

+0

はい、あなたは正しいです!しかし、私は私のラップトップに問題があり、私はそれを修復しています。今私はコードを書くことができるまで私の問題について考えている。申し訳ありません – MRB

+0

"通知された条件変数"のようなものはありません。条件変数について理解する上で最も重要なことは、ステートレスであることです。 –

答えて

13

スレッド2は誰かがnotifyを呼び出すまでブロックします。呼び出し時に待機中のリリーススレッドに通知するための呼び出し。待機中のスレッドがない場合、何もしません。彼らは救われません。

+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がロックを持っている、いずれかのキューが空ではないので、それは待つことはありません場合は

  • が(失われないもの)(そう知らせる「失うこと」無害である)、またはそれが通知を待ってそこに座っています。

  • スレッド1がロックを取得した場合は、キューに要素が格納されます。 thread2が待機していた場合は、正しく通知されます。スレッド2がまだミューテックスを待っていた場合、待ち行列には少なくとも1つの要素が存在するため、待ち状態にはならないので、通知を失うことは無害です。

このように、通知は最初に必要でない場合にのみ失われます。

通知を「失う」結果が生じる条件変数の使用方法が異なる場合は、競合状態にあるか間違ったツールを使用していると思われます。

+0

あなたは私の編集を見ることができますか?ありがとう。 – MRB

+0

新しい質問をする場合は、新しい質問を投稿してください。あなたの古い質問を編集して無関係なものを変更/追加しないでください。また、私はbcReadlBadly mIndented bAND lIntentionally pabfcated bcCodeはできません。 – DanielKO

関連する問題