C ++中队列的并发处理

时间:2017-10-19 11:04:29

标签: c++ multithreading image concurrency queue

我正在编写一个小程序来同时对图片进行操作。

想法是让程序处理命令行输入,然后在不同的线程上执行操作。例如,如果用户想要将5张图片加载到程序中,则负载将并行发生。这同样适用于操作。在加载一个图像的同时,另一个图像可能会模糊,另一个图像可能会旋转。

现在我有以下结构:

--Main.cpp
--Picture.h
--Tools.h
--Event.h
--ConcurrentQueue.h

对于每个命令(输入),我创建一个存储在队列中的事件。然后,许多工作线程检查队列并执行每个事件。

似乎发生的一个问题是同一图像上的操作可能同时发生(如果一个命令是“调整大小img1”而下一个命令是“crop img1”),我想避免这种情况(操作在相同的图像应按顺序发生。

另外,如果我创建10个工作线程,似乎每个线程只处理队列中的一个事件,而不是连续轮询(只发生10个事件)。

这是传递给线程构造函数的worker函数的简化版本:

void work(Tools *lib) {
  if (lib == nullptr) {
    cerr << "lib is null";
    exit(1);
  }
  std::thread::id this_id = std::this_thread::get_id();
  cout << "Work function entered by thread " << this_id << endl;
  while (!finished.load()) {
    Event item = event_queue.pop();
    if (item.isEventA()) {
      lib->lock_picture(filename);
      /* 
      Do picture work here
      */
      lib->unlock_picture(filename);
    } else {
      lib->lock_picture(filename);
      /* 
      Do picture work here
      */
      lib->unlock_picture(filename);
    }
  }
}

Tools是管理转换的类。在Picture我有一个互斥和两个函数

void Picture::lock() {
    picture_mutex.lock();
}

void Picture::unlock() {
    picture_mutex.unlock();
}

这些是从Tools函数lock_pictureunlock_picture调用的。

Queue是一个线程安全的实现。我正在使用全局变量finished来表示线程停止工作(虽然目前似乎不起作用)。

欢迎任何有关改进的想法!

1 个答案:

答案 0 :(得分:0)

您应该忘记queue / mutex等等并切换到asio,asio::strand类提供序列化执行,这就是您要查找的内容。

struct Picture
{
    asio::strand _strand;
    std::string _file_name;

    Picture(asio::io_service&);
    void Work1();
    void Work2();
    void Work3();
};

void main( bla bla bla)
{
    asio::io_service io_service;
    vector<Picture> Pictures(bla bla bla);
    for_each(Pictures.begin(), Pictures.end, [](auto& elt){
       elt._wrap.post([elt](){elt.Work1();});
       elt._wrap.post([elt](){elt.Work2();});
       elt._wrap.post([elt](){elt.Work3();}));

    // Create a pool of threads to run all of the io_services.
    std::vector<shared_ptr<thread> > threads;
    for (std::size_t i = 0; i < 10; ++i)
    threads.push_back( make_shared<thread>(
       [&io_service]() {io_service.run(); }));
    // Wait for all threads in the pool to exit.
    for (std::size_t i = 0; i < threads.size(); ++i)
       threads[i]->join();
}

asio以standaloneboost library提供。

享受!