哪个是产生线程的最佳方法?

时间:2019-05-27 11:15:47

标签: c++ multithreading c++11

程序语言:C ++ 11
我使用管道线程模式处理数据。
一个线程生成数据。
一线程处理数据。
虽然没有数据要处理,但这是产生线程的最佳方法?
现在我用

std::this_thread::sleep_for(100ms); 
  1. 我想知道是否有更好的生产方法?
  2. 如果睡眠充足,那么多长时间可以睡个好觉?

3 个答案:

答案 0 :(得分:6)

  

哪个是产生线程的最佳方法?

它是std::this_thread::yield

  

现在我使用

std::this_thread::sleep_for(100ms);

虽然睡眠确实会产生线程副作用,但这还不是全部。顾名思义,它会在给定时间内阻止线程。

但是,尚不清楚产量或睡眠在生产者/消费者案例(例如您所描述的案例)中如何有用。您可能应该做的是改为等待条件变量。

答案 1 :(得分:2)

介绍一个等待条件,您的使用者线程需要等待。 生产者生成数据后,它可以通知您的使用者线程,直到使用者等待。

答案 2 :(得分:0)

通过数据队列进行通信。如果需要,队列可以具有最大大小。

一个线程生成数据并将其推入队列。

另一个线程将数据弹出队列并进行处理。

当队列为空时,使用线程在队列中等待要推送的新数据。

当队列已满时,生产线程在队列中等待弹出数据。或者,您可以丢弃并替换队列中的等待数据。这取决于您的数据模型是什么样的(最新是重要的,还是有序的所有都是重要的)

简单队列:

template<class T>
struct threadsafe_queue {
  T pop() {
    auto l = lock();
    cv.wait( l, [&]{ return !data.empty(); } );
    T r = std::move(data.front());
    data.pop_front();
    return r;
  }
  void push( T&& t ) {
    auto l = lock();
    data.push_back( std::move(t) );
    cv.notify_one();
  }
  void abandon() {
    auto l = lock();
    data = {};
  }
private:
  std::unique_lock<std::mutex> lock() { return std::unique_lock<std::mutex>(m); }

  std::mutex m;
  std::condition_variable cv;
  std::deque<T> data;
};

对条目数有限制的人应该有第二个condition_variable来通知某人弹出,并且推送应查看您是否已达到限制。

支持“已满时覆盖”成为另一种选择。一个1元素的“最新”看起来像:

template<class T>
struct mono_threadsafe_queue {
  // waits until we have data, then returns it.
  T pop() {
    auto l = lock();
    cv_hasdata.wait( l, [&]{ return (bool)data; } );
    T r = std::move(*data);
    data = boost::none;
    cv_hasroom.notify_one();
    return r;
  }
  // waits for there to be room if there is none.
  void push( T&& t ) {
    auto l = lock();
    cv_hasroom.wait( l, [&]{ return !(bool)data; } );
    data =  std::move(t);
    cv_hasdata.notify_one();
  }
  void replace( T&& t ) {
    auto l = lock();
    data =  std::move(t);
    cv_hasdata.notify_one();
  }
  // replaces data if f returns true, or if there is no data
  // imagine data with a timestamp, and we only want to replace it with
  // newer data
  template<class F>
  void replace_if( T&& t, F&& f ) {
    auto l = lock();
    if (!data || !f(*data))
    {
      data =  std::move(t);
      cv_hasdata.notify_one();
    }
  }
  void abandon() {
    auto l = lock();
    data = boost::none;
    cv_hasroom.notify_one();
  }

private:
  std::unique_lock<std::mutex> lock() { return std::unique_lock<std::mutex>(m); }

  std::mutex m;
  std::condition_variable cv_hasdata;
  std::condition_variable cv_hasroom;
  boost::optional<T> data;
};