2013-10-02 28 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

相关问题