防止在C ++中进行交错

时间:2014-08-18 18:25:43

标签: c++ multithreading concurrency

考虑以下示例类,它允许一个线程等待来自另一个线程的信号。

class Sync
{
    std::mutex mtx, access;
    std::condition_variable cv;
    bool waiting;

public:
    Sync()
        : waiting(false)
    {
    }
    Sync(const Sync&);
    ~Sync()
    {
        sendSignal();
    }

    void waitForSignal()
    {
        access.lock();
        if (!waiting)
        {
            std::unique_lock<std::mutex> lck (mtx);
            waiting = true;
            access.unlock();

            // in the time between these two statements, 'sendSignal()' acquires 
            // the lock and calls 'cv.notify_all()', thus the signal was missed. 

            cv.wait(lck);
        }
        else
            access.unlock();
    }
    void sendSignal()
    {
        access.lock();
        if (waiting)
        {
            std::unique_lock<std::mutex> lck (mtx);
            cv.notify_all();
            waiting = false;
        }
        access.unlock();
    }
};

我遇到的问题是,在解锁“访问”期间,由于交错而偶尔会丢失信号。互斥和呼叫&#39; wait()&#39;在condition_variable上。我该如何防止这种情况?

1 个答案:

答案 0 :(得分:2)

您应该只有一个互斥锁。我不明白为什么你需要访问。使用mtx保护等待变量和条件变量。

class Sync
{
    std::mutex mtx;
    std::condition_variable cv;
    bool waiting;

public:
    Sync()
        : waiting(false)
    {
    }
    Sync(const Sync&);
    ~Sync()
    {
        sendSignal();
    }

    void waitForSignal()
    {
        std::unique_lock lck (mtx);
        if (!waiting)
        {
            waiting = true;

            cv.wait(lck);
        }
    }
    void sendSignal()
    {
        std::unique_lock lck (mtx);
        if (waiting)
        {
            cv.notify_all();
            waiting = false;
        }
    }
};

等待变量和条件变量状态绑定在一起,因此它们应被视为一个关键部分。