What happens if i call wait on a notified conditio

2020-03-16 04:16发布

Suppose I have two threads and one shared c++ 11 condition variable. What whould happen if thread1 call notify and after that thread2 call wait? Will thread2 block forever or it will continue it's work due to call of notify by thread1?

Edit:

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() {};

    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)
            {
                return;
            }
            else if(lLoopCounter == lLoopCount)
            {
                bcLockGuard<bcMutex> lGuard(mMutex);
                mCond.wait(mMutex);                           
            }
            else
            {
                continue;
            }
        }

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

        bcBOOL TryLock() 
        {
        };
    };

I want to write a custom mutex such that each thread can provide an argument that represents the complexity of operations that the current thread wants to execute. If the complexity of the operation is low other threads will be in a loop like a spin lock but if the complexity of the operation is medium each thread will iterate 50 times and then will sleep by condition variable and if operation is very complex other threads will go to sleep directly.

now assume thread1 locks this mutex and thread2 goes for waiting due to its loopCounter reaching its end and right before locking the condition variable's mutex, thread1 calls notify on the condition variable. Now thread2 will sleep until another thread locks the custom mutex and then calls unlock on it.

I am new to multithreading and I want to learn. I know that my class may contain errors or may be completely wrong, but is there any way to correct this problem or a good algorithm to write such a mutex.

2条回答
一纸荒年 Trace。
2楼-- · 2020-03-16 04:41

Usually both the code that decides to wait and the code that decides to notify share the same mutex. So thread2 will never "miss" the notify from thread1.

Here's the classic lock-based concurrent queue example:

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;
}

Assume thread1 and thread2 are running push() and pop() respectively. Only one of them will be in the critical section at a time.

  • If thread2 has the lock, either it never waits because the queue is not empty (so "losing" a notify is harmless), or it sits there waiting for a notify (which won't be lost).

  • If thread1 got the lock, it will put an element in the queue; if thread2 was waiting, it will get notified properly; if thread2 was still waiting for the mutex, it will never wait, as there is at least one element on the queue, so losing a notify is harmless.

In this manner, a notify is only lost if it was not needed in the first place.

Now, if you have a different usage for condition variables in mind, where "losing" a notification has any consequence, I believe you either have a race condition, or are using the wrong tool altogether.

查看更多
劳资没心,怎么记你
3楼-- · 2020-03-16 04:43

Thread2 will block until someone calls notify. Calls to notify release threads that are waiting at the time of the call. If there are no threads waiting, they do nothing. They aren't saved.

查看更多
登录 后发表回答