【问题标题】:Synchronization with blocking call与阻塞调用同步
【发布时间】:2015-05-08 10:37:36
【问题描述】:

假设我有一个具有以下接口的类:

class IEvent
{
    void SetEvent() = 0;
    void WaitForEvent() = 0;
}

WaitForEvent() 是一个阻塞函数,它一直等到另一个线程调用SetEvent() 函数。

我正在为这个类编写单元测试,并且想要以下场景:

第一个线程调用WaitForEvent()。在第二个线程调用SetEvent() 之后。

如何同步SetEvent()调用将始终跟随WaitForEvent()调用的线程?

我不想使用任何睡眠,因为我希望单元测试尽可能快地运行。

【问题讨论】:

  • 这对我测试类似情况很有帮助:stackoverflow.com/questions/10767131/…
  • 你正在为一个接口编写单元测试?
  • 不,我有一个实现。而实际的界面更加复杂。但这对那个问题来说是不必要的。

标签: c++ multithreading testing concurrency


【解决方案1】:

这是我能做到的最好的了

#include <mutex>
#include <condition_variable>
#include <thread>
#include <iostream>

class IEvent
{
public:
    virtual void SetEvent() = 0;
    virtual void WaitForEvent() = 0;
};

class EventClass : public IEvent
{
public:
    void SetEvent() override {
        std::unique_lock<std::mutex> lock { _mutex };
        std::cout << "setting event\n";
        _event = true;
        lock.unlock();
        _cv.notify_all();
    }

    void WaitForEvent() override {
        std::unique_lock<std::mutex> lock { _mutex };
        std::cout << "waiting for event\n";
        _cv.wait(lock, [this]{ return _event; });
        std::cout << "waiting complete\n";
    };

private:
    std::mutex _mutex;
    std::condition_variable _cv;
    bool _event = false;
};

int main()
{
    EventClass object;

    std::mutex cv_mutex;
    std::condition_variable may_set_cv;
    bool may_set_event = false;

    auto setting_thread = std::thread([&]{
        std::unique_lock<std::mutex> lock { cv_mutex };
        may_set_cv.wait(lock,
                        [&] {
                            return may_set_event;
                        });
        object.SetEvent();
    });
    std::unique_lock<std::mutex> lock { cv_mutex };
    may_set_event = true;
    lock.unlock();
    may_set_cv.notify_one();

    // tiny race condition here

    object.WaitForEvent();

    setting_thread.join();
}

【讨论】:

  • 谢谢。我考虑过类似的东西(非 C++11)。如果没有完美的解决方案,这将是我的选择。
  • 近乎完美。您唯一无法控制的是通知调用和调用 WaitForEvent 之间的几个时钟周期 - 我们在这里谈论的是纳秒。如果第二个线程能够在那个时间唤醒并抢占呼叫,我将成为猴子的叔叔:-)
猜你喜欢
  • 2018-04-06
  • 2020-09-01
  • 1970-01-01
  • 2012-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-14
  • 2013-07-20
相关资源
最近更新 更多