首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何测试阻塞队列实际阻塞

如何测试阻塞队列实际阻塞
EN

Stack Overflow用户
提问于 2017-11-17 23:29:06
回答 3查看 856关注 0票数 4

我有一个阻塞队列(我真的很难改变它的实现),我想测试它是否真的阻塞了。特别是,如果队列为空,则pop方法必须阻塞,并在执行push时立即解除阻塞。请参阅下面的伪C++11代码进行测试:

代码语言:javascript
复制
BlockingQueue queue; // empty queue

thread pushThread([] 
{ 
    sleep(large_delay);
    queue.push(); 
});

queue.pop();

显然它并不完美,因为即使延迟很大,整个线程pushThread也可能在pop被调用之前执行并终止,而且延迟越大,我必须等待测试结束的时间就越长。

如何正确地确保在调用push之前执行pop,即在push返回之前阻塞?

EN

回答 3

Stack Overflow用户

发布于 2017-11-18 03:52:28

如果不向BlockingQueue添加一些额外的状态和接口,我认为这是不可能的。

证据是这样的。您希望等到pop上的读取线程被阻塞。但是没有办法将其与将要执行pop的线程区分开来。无论您在调用pop之前或之后放置什么内容,这一点都是正确的。

如果你真的想以100%的可靠性修复这个问题,你需要在队列中添加一些状态,由队列的互斥锁来保护,这意味着“有人在等待”。然后,pop调用必须在原子释放互斥锁之前更新状态,并在内部条件变量上休眠。push线程可以获取互斥锁并等待,直到“有人在等待”。为了避免这里出现繁忙循环,您需要再次使用条件变量。

所有这些机器几乎和队列本身一样复杂,所以也许你也想测试一下……在这类多线程代码中,“代码覆盖率”--甚至可以说是单元测试本身--这样的概念有点崩溃了。有太多可能的操作交错。

在实践中,我可能会采用你最初的睡眠方法。

票数 1
EN

Stack Overflow用户

发布于 2017-11-18 06:09:25

代码语言:javascript
复制
template<class T>
struct async_queue {
  T pop() {
    auto l = lock();
    ++wait_count;
    cv.wait( l, [&]{ return !data.empty(); } );
    --wait_count;
    auto r = std::move(data.front());
    data.pop_front();
    return r;
  }
  void push(T in) {
    {
      auto l = lock();
      data.push_back( std::move(in) );
    }
    cv.notify_one();
  }
  void push_many(std::initializer_list<T> in) {
    {
      auto l = lock();
      for (auto&& x: in) 
        data.push_back( x );
    }
    cv.notify_all();
  }
  std::size_t readers_waiting() {
    return wait_count;
  }
  std::size_t data_waiting() const {
    auto l = lock();
    return data.size();
  }
private:
  std::queue<T> data;
  std::condition_variable cv;
  mutable std::mutex m;
  std::atomic<std::size_t> wait_count{0};
  auto lock() const { return std::unique_lock<std::mutex>(m); }

};

或者诸如此类的。

在推送线程中,忙等待readers_waiting,直到它超过1。

在这一点上,您拥有锁,并且在解锁之前处于cv.wait中。做一个push

从理论上讲,无限慢的读取器线程可能已经进入cv.wait,并且在调用push时仍在计算第一个lambda,但无限慢的读取器线程与阻塞的读取器线程没有什么不同……

然而,这确实会处理线程启动缓慢等问题。

除了调试之外,使用readers_waitingdata_waiting做任何事情通常都是一种代码气味。

票数 1
EN

Stack Overflow用户

发布于 2017-11-17 23:56:03

您可以使用std::condition_variable来完成此任务。cppreference.com的帮助页面实际上显示了一个非常好的消费者-生产者示例,它应该正是您正在寻找的:http://en.cppreference.com/w/cpp/thread/condition_variable

编辑:实际上,德语版本的cppreference.com有一个更好的例子:-) http://de.cppreference.com/w/cpp/thread/condition_variable

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47354085

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档