在线程之间共享数据

Sharing Data Among Threads

本文关键字:数据 共享 之间 线程      更新时间:2023-10-16

我正在编写Windows 10应用程序,该应用程序通过串行从4个不同的传感器(编码器和IMU)收集数据。我在C 11的Visual Studio中写这篇文章。我每个传感器有一个线程,可以在无限的循环中连续从中删除数据。

作为我的新手,我目前正在努力以某种方式"收集"一个线程中的数据。我发现我可以使用条件变量向另一个线程发出信号(在我的情况下,我假设每个传感器完成时会发出主螺纹的信号)。在这种情况下,我是否必须将数据存储在全局变量中,并在我(从传感器线程中)写入MUTEX并从中读取(在主循环中)?

来保护它?

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

如果这些是愚蠢的问题,我深表歉意,但我真的需要帮助。任何示例代码都将不胜感激。

这看起来像我要实现的。我真的怀疑,如果您在输入之间有毫秒(这是很大的时间),您会遇到麻烦。

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

#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();  
}

我将通过使用boost :: asio库在每个传感器上设置异步读取。当异步读取完成时,它调用一个读取器来解析数据,然后设置另一个异步读取。所有读取的操作者都以同一线程运行 - 这使生活变得更加简单。