c ++ - 在线程之间共享数据

时间:2017-08-31 00:29:04

标签: c++ multithreading c++11 data-sharing

我正在编写一个Windows 10应用程序,它通过串行从4个不同的传感器(编码器和IMU)收集数据。我是在c ++ 11中的Visual Studio中编写的。每个传感器有一个线程,可以在无限循环中连续从中获取数据。

由于我是新手,我目前正在努力以某种方式“收集”单个线程中的数据。我发现我可以使用条件变量来指示另一个线程(在我的情况下,我假设我会在每个传感器完成时发出主线程信号)。在这种情况下,我是否必须将数据存储在全局变量中,并在我写入(从传感器线程)并从中读取(在主循环中)时使用互斥锁保护它?

但是,我担心这个过程对我的应用程序来说可能太慢(每个传感器每1-2毫秒获取一次新数据),因此在主线程读取时锁定数据的过程中,我会丢失一些数据。 (在每个传感器线程内)将数据存储在局部变量中然后将此变量复制到全局变量,并且主线程仅从第二个变量读取是否有意义?

如果这些是愚蠢的问题,我道歉,但我真的需要帮助。任何示例代码都将非常感激。

2 个答案:

答案 0 :(得分:1)

这看起来就像我要实施的那样。如果输入之间有毫秒(这是一段很长的时间),我真的怀疑你会遇到吞吐量问题。

如果有人发现下面有任何微妙的错误,请告诉我。

#include <thread>
#include <iostream>
#include <chrono>
#include <queue>
#include <mutex>
#include <vector>
#include <condition_variable>

using namespace std::chrono_literals;
using std::vector;
using std::thread;
using std::unique_lock;
using std::mutex;
using std::condition_variable;
using std::queue;

class WorkQueue
{
  condition_variable work_available;
  mutex work_mutex;
  queue<int> work;

public:
  void push_work(int item)
  {
    unique_lock<mutex> lock(work_mutex);

    bool was_empty = work.empty();
    work.push(item);

    lock.unlock();

    if (was_empty)
    {
      work_available.notify_one();
    }    
  }

  int wait_and_pop()
  {
    unique_lock<mutex> lock(work_mutex);
    while (work.empty())
    {
      work_available.wait(lock);
    }

    int tmp = work.front();
    work.pop();
    return tmp;
  }
};

int main() {
  WorkQueue work_queue;

  auto producer = [&]() {
    while (true) {
      work_queue.push_work(10);
      std::this_thread::sleep_for(2ms);
    }
  };

  vector<thread> producers;
  producers.push_back(std::thread(producer));
  producers.push_back(std::thread(producer));
  producers.push_back(std::thread(producer));
  producers.push_back(std::thread(producer));

  std::thread consumer([&]() {        
    while (true)
    {
      int work_to_do = work_queue.wait_and_pop();
      std::cout << "Got some work: " << work_to_do << std::endl;
    }
  });

  std::for_each(producers.begin(), producers.end(), [](thread &p) {
    p.join();
  });    

  consumer.join();  
}

答案 1 :(得分:0)

我会通过使用boost::asio库在每个传感器上设置异步读取来处理这个问题。异步读取完成后,它会调用读取处理程序来解析数据,然后设置另一个异步读取。所有读取处理程序都在同一个线程中运行 - 这使生活变得更加简单。