Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在Boost中同步线程_C++_Multithreading_Boost_Boost Thread - Fatal编程技术网

C++ 在Boost中同步线程

C++ 在Boost中同步线程,c++,multithreading,boost,boost-thread,C++,Multithreading,Boost,Boost Thread,我试图创建一个应用程序,创建一个主线程和10个从线程。我想在主线程运行后运行一次从线程。因此,对于每个主线程执行,每个从线程将执行一次。我试图用两个不同的条件变量来处理这个问题。因此,一个用于从属线程,以便它们可以等待主线程通知它们,另一个条件变量用于在每个子线程完成其任务后发出信号的主线程,以便主线程可以检查是否所有从属线程都已完成。代码如下: // STD #include <iostream> #include <vector> // BOOST #inclu

我试图创建一个应用程序,创建一个主线程和10个从线程。我想在主线程运行后运行一次从线程。因此,对于每个主线程执行,每个从线程将执行一次。我试图用两个不同的
条件变量来处理这个问题。因此,一个用于从属线程,以便它们可以等待主线程通知它们,另一个
条件变量
用于在每个子线程完成其任务后发出信号的主线程,以便主线程可以检查是否所有从属线程都已完成。代码如下:

// STD 
#include <iostream>
#include <vector>


// BOOST
#include <boost/thread.hpp>
#include <boost/atomic.hpp>

std::vector<boost::thread*> threads;

std::vector<boost::mutex*> data_ready_mutex;
std::vector<boost::condition_variable*> cond;
std::vector<bool> data_ready;
std::vector<int> num_run;

boost::mutex check_finish_mutex;
std::vector<bool> finished;

boost::atomic<int> data;
boost::atomic<int> next_thread_id;

boost::mutex finished_task_mutex;
boost::condition_variable finished_task_cond;
bool finished_task = false;

void signal_finished(const int& id)
{
  {
    boost::lock_guard<boost::mutex> lock(finished_task_mutex);
    finished[id] = true;
    finished_task = true;
  }
  finished_task_cond.notify_all();
}

void signal_slave(const int& id)
{
  {
    boost::lock_guard<boost::mutex> lock(*data_ready_mutex[id]);

    data_ready[id] = true;
  }
  cond[id]->notify_all();
}

void slave_therad()
{
  int id = next_thread_id++;

  std::cout << "( " << id << " ) slave_thread created\n";
  while (true)
  {
    boost::unique_lock<boost::mutex> lock(*data_ready_mutex[id]);
    while (!data_ready[id])
    {
      cond[id]->wait(lock);
    }

    finished[id] = false;

    data_ready[id] = false;

    data++;

    num_run[id]++;

    signal_finished(id);
  }
}

void main()
{
  size_t nThreads = 10;

  data_ready_mutex.resize(nThreads);
  cond.resize(nThreads);
  data_ready.resize(nThreads);
  finished.resize(nThreads);
  num_run.resize(nThreads, 0);
  for (size_t i = 0; i < nThreads; i++)
  {
    data_ready_mutex[i] = new boost::mutex();
    cond[i] = new boost::condition_variable();
    data_ready[i] = false;
    finished[i] = false;
  }

  for (size_t i = 0; i < nThreads; i++)
  {
    threads.push_back(new boost::thread(slave_therad));
  }

  while (true)
  {
    clock_t start_time = clock();

    for (size_t i = 0; i < threads.size(); i++)
      signal_slave(static_cast<int>(i));

    while (true)
    {
      boost::unique_lock<boost::mutex> lock(finished_task_mutex);
      while (!finished_task)
      {
        finished_task_cond.wait(lock);
      }
      finished_task = false;

      size_t i = 0;
      for (; i < finished.size(); i++)
      {
        if (!finished[i]) break;
      }
      if (i == finished.size()) break;
    }

    clock_t end_time = clock();

    std::cout << "Elapsed Time = " << static_cast<float>(end_time - start_time) / CLOCKS_PER_SEC << std::endl;

    for (size_t i = 0; i < threads.size(); i++)
      finished[i] = false;
  }

  for (size_t i = 0; i < nThreads; i++)
  {
    threads[i]->join();
  }
}
// STD 
#include <iostream>
#include <vector>


// BOOST
#include <boost/thread.hpp>
#include <boost/atomic.hpp>

boost::barrier* barrier;                            //!< barrier to make sure all the slave threads are done their tasks.

std::vector<boost::thread*> threads;

std::vector<boost::mutex*>  data_ready_mutex;       //!< Mutex to guard the data_ready 
std::vector<bool>           data_ready;             //!< Shows if the data is ready for the slave thread or not.
std::vector<boost::condition_variable*> cond;       //!< conditional variable to wait on data being ready for the slave thread.

std::vector<int> num_run;                           //!< Stores the number of times each slave thread is run.

boost::atomic<int> data;                            //!< Stores the data processed by each slave thread
boost::atomic<int> next_thread_id;                  //!< id for the next thread (used for giving an id from 0,..., nThreads-1

boost::atomic<int> num_threads_done;                //!< Stores the number of slave threads which has finished their task

std::vector<bool> finished;                         //!< Array which stores if all the slave threads are done or not.
boost::mutex finished_task_mutex;                   //!< mutex to guard the finished_task variable
boost::condition_variable finished_task_cond;       //!< Conditional variable to wait for all the threads to finish they tasks.
boost::atomic<bool> finished_task(false);           //!< Variable which stores if the task of slave_threads are finished or not.

void signal_finished(const int& id)
{
  {
    boost::lock_guard<boost::mutex> lock(finished_task_mutex);
    finished[id] = true;
    finished_task = true;
  }
  finished_task_cond.notify_all();
}

void signal_slave(const int& id)
{
  {
    boost::lock_guard<boost::mutex> lock(*data_ready_mutex[id]);

    data_ready[id] = true;
  }
  cond[id]->notify_all();
}

void slave_therad()
{
  int id = next_thread_id++;

  std::cout << "( " << id << " ) slave_thread created\n";
  while (true)
  {
    boost::unique_lock<boost::mutex> lock(*data_ready_mutex[id]);
    while (!data_ready[id])
    {
      cond[id]->wait(lock);
    }

    finished[id] = false;

    data_ready[id] = false;

    data++;

    num_run[id]++;

    barrier->wait();

    signal_finished(id);
  }
}

void main()
{
  size_t nThreads = 10;

  data_ready_mutex.resize(nThreads);
  cond.resize(nThreads);
  data_ready.resize(nThreads);
  finished.resize(nThreads);
  num_run.resize(nThreads, 0);
  for (size_t i = 0; i < nThreads; i++)
  {
    data_ready_mutex[i] = new boost::mutex();
    cond[i] = new boost::condition_variable();
    data_ready[i] = false;
    finished[i] = false;
  }

  barrier = new boost::barrier(nThreads);

  for (size_t i = 0; i < nThreads; i++)
  {
    threads.push_back(new boost::thread(slave_therad));
  }

  while (true)
  {
    clock_t start_time = clock();

    for (size_t i = 0; i < threads.size(); i++)
      signal_slave(static_cast<int>(i));

    while (true)
    {
      boost::unique_lock<boost::mutex> lock(finished_task_mutex);
      while (!finished_task)
      {
        finished_task_cond.wait(lock);
      }
      finished_task = false;
      break;
    }

    clock_t end_time = clock();

    std::cout << "Elapsed Time = " << static_cast<float>(end_time - start_time) / CLOCKS_PER_SEC << std::endl;

    for (size_t i = 0; i < threads.size(); i++)
      finished[i] = false;
  }

  for (size_t i = 0; i < nThreads; i++)
  {
    threads[i]->join();
  }
}
//#define SYNC_WITH_BARRIER
#define SYNC_WITH_ATOMICS

// STD 
#include <iostream>
#include <vector>


// BOOST
#include <boost/thread.hpp>
#include <boost/atomic.hpp>
#include <boost/ptr_container/ptr_vector.hpp>

std::vector<boost::thread*> threads;

boost::atomic<int> next_thread_id(0);

boost::mutex finished_task_mutex;
boost::condition_variable finished_task_cond;
bool finished_task = false;

boost::atomic<int> num_finished_tasks(0);

struct Work
{
  Work(boost::barrier& _barrier) : b(&_barrier)
  {

  }

  boost::barrier*           b;
  boost::mutex              data_ready_mutex;
  boost::condition_variable data_ready_cond;
  bool                      data_ready;
  int                       num_run;
  boost::atomic<int>        data;
  bool                      finished;

  void signal_slave()
  {
    {
      boost::lock_guard<boost::mutex> lock(data_ready_mutex);
      data_ready = true;
      data_ready_cond.notify_all();
    }    
  }

  void slave_therad()
  {
    int id = next_thread_id++;

    std::cout << "( " << id << " ) slave_thread created\n";
    while (true)
    {
      boost::unique_lock<boost::mutex> lock(data_ready_mutex);
      while (!data_ready)
      {
        data_ready_cond.wait(lock);
      }

      finished = false;

      data_ready = false;

      data++;

      num_run++;

#ifdef SYNC_WITH_BARRIER
      b->count_down_and_wait();
#else 
#ifdef SYNC_WITH_ATOMICS
      num_finished_tasks++;
#endif
#endif
    }
  }

};

#include <boost/chrono.hpp>
#include <boost/chrono/chrono_io.hpp>

using hrc = boost::chrono::high_resolution_clock;

void main()
{
  size_t nThreads = 10;

  boost::thread_group tg;
  boost::ptr_vector<Work> work_items;
  work_items.reserve(nThreads);

  boost::barrier finish(nThreads + 1); // one for the main thread

  for (size_t i = 0; i < nThreads; i++)
  {
    work_items.push_back(new Work(finish));
    tg.create_thread(boost::bind(&Work::slave_therad, boost::ref(work_items.back()))); 
  }

  while (true)
  {
    auto start_time = hrc::now();

    num_finished_tasks = 0;

    for (size_t i = 0; i < work_items.size(); i++)
      work_items[i].signal_slave();

#ifdef SYNC_WITH_BARRIER
    finish.count_down_and_wait();
#else
#ifdef SYNC_WITH_ATOMICS
    while (true) if (num_finished_tasks == work_items.size()) break;
#endif
#endif

    clock_t end_time = clock();

    std::cout << "Elapsed Time = " << hrc::now() - start_time << std::endl;

  }

  for (size_t i = 0; i < nThreads; i++)
  {
    threads[i]->join();
  }
}
@即使有了屏障,它也陷入了僵局mmostajab

既然你没有展示你在那里做的任何事情,让我把你收到的所有建议中的一大块合并起来,给你一个创业的动力:

#include <boost/atomic.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <vector>

namespace /*static*/ {
    boost::atomic<int> data;
    boost::atomic<int> num_threads_done;

    struct Work {
        void signal_slave()
        {
            boost::lock_guard<boost::mutex> lock(data_ready_mutex);
            data_ready = true;
            cond.notify_all();
        }

        void slave_thread()
        {
            static boost::atomic_int _id_gen(0);
            id = _id_gen++;

            std::cout << "(" << id << ") slave_thread created\n";
            while (true) {

                boost::unique_lock<boost::mutex> lock(data_ready_mutex);
                cond.wait(lock, [&]{ return data_ready; });

                data_ready = false;

                data++;

                num_run++;

                num_threads_done++;
            }
        }

      private:
        int id          = 0;
        bool data_ready = false;
        int  num_run    = 0;

        boost::mutex data_ready_mutex;
        boost::condition_variable cond;

    };

}

#include <boost/chrono.hpp>
#include <boost/chrono/chrono_io.hpp>

using hrc = boost::chrono::high_resolution_clock;

int main()
{
    boost::thread_group tg;

    size_t nThreads = 10;

    std::vector<Work> works(nThreads);

    for (size_t i = 0; i < nThreads; i++) {
        tg.create_thread(boost::bind(&Work::slave_thread, boost::ref(works[i])));
    }

    while (true) {
        auto start_time = hrc::now();

        for (auto& w : works)
            w.signal_slave();

        std::cout << "Elapsed Time = " << (hrc::now()-start_time) << std::endl;
    }

    tg.join_all();
}
#包括
#包括
#包括
#包括
#包括
名称空间/*静态*/{
原子数据;
boost::原子线程数完成;
结构工程{
无效信号_从机()
{
boost::lock\u guard lock(数据就绪互斥锁);
数据_ready=true;
条件通知所有人();
}
void slave_thread()
{
静态boost::atomic_int_id_gen(0);
id=_id_gen++;

std::cout我试图更改@sehe答案,因此它正好解决了我正在寻找的问题,我实现了以下代码:

#include <boost/atomic.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <vector>

namespace /*static*/ {
  boost::atomic<int> data;

  boost::barrier*           slave_thread_finished_barrier;
  boost::mutex              slave_thread_finished_mutex; 
  boost::condition_variable slave_thread_finished_cond;
  bool                      slave_thread_finished = false;

  struct Work {
    void signal_slave()
    {
      boost::lock_guard<boost::mutex> lock(data_ready_mutex);
      data_ready = true;
      cond.notify_all();
    }

    void slave_thread()
    {
      static boost::atomic_int _id_gen(0);
      id = _id_gen++;

      std::cout << "(" << id << ") slave_thread created\n";
      while (true) {

        boost::unique_lock<boost::mutex> lock(data_ready_mutex);
        cond.wait(lock, [&]{ return data_ready; });

        data_ready = false;

        data++;

        num_run++;

        slave_thread_finished_barrier->wait();

        // signaling the main thread that the slave threads are done.
        if (id == 0)
        {
          boost::lock_guard<boost::mutex> lock(slave_thread_finished_mutex);
          slave_thread_finished = true;
          slave_thread_finished_cond.notify_one();
        }

      }
    }

  private:
    int id = 0;
    bool data_ready = false;
    int  num_run = 0;

    boost::mutex data_ready_mutex;
    boost::condition_variable cond;

  };

}

#include <boost/chrono.hpp>
#include <boost/chrono/chrono_io.hpp>

using hrc = boost::chrono::high_resolution_clock;

int main()
{
  boost::thread_group tg;

  size_t nThreads = 10;

  slave_thread_finished_barrier = new boost::barrier(nThreads);
  std::vector<Work> works(nThreads);

  for (size_t i = 0; i < nThreads; i++) {
    tg.create_thread(boost::bind(&Work::slave_thread, boost::ref(works[i])));
  }

  while (true) {
    auto start_time = hrc::now();

    for (auto& w : works)
      w.signal_slave();

    // Wait for slave threads to finish.
    boost::unique_lock<boost::mutex> lock(slave_thread_finished_mutex);
    slave_thread_finished_cond.wait(lock, [&]{ return slave_thread_finished; });
    slave_thread_finished = false;

    std::cout << "Elapsed Time = " << (hrc::now() - start_time) << std::endl;
  }

  tg.join_all();
}
#包括
#包括
#包括
#包括
#包括
名称空间/*静态*/{
原子数据;
boost::屏障*从线程完成屏障;
互斥从线程完成互斥;
boost::条件变量从线程完成条件;
bool slave_thread_finished=false;
结构工程{
无效信号_从机()
{
boost::lock\u guard lock(数据就绪互斥锁);
数据_ready=true;
条件通知所有人();
}
void slave_thread()
{
静态boost::atomic_int_id_gen(0);
id=_id_gen++;

std::cout@Niall我试图在设置cond变量等之后创建线程,但它仍然处于死锁状态。您可以
std::move()
a
std::thread
到容器中,避免动态分配,这对我来说已经足够合理了。Ulrich是对的,尝试将mThread.join();放在main()的末尾这不是我的意思,@Ivan.
main()
中无用的线程
mThread
可以用对线程函数的简单调用来替换。顺便说一句:
main()
已经在线程中运行(你总是至少有一个线程!),因此名称有点误导。或者屏障/信号量这做了完全不同的事情,因为原始主循环总是向所有工作线程发出一个任务,然后等待他们完成,然后再处理下一轮。@UlrichEckhardt是的。你是对的,但我将条件变量添加到主线程以等待从线程eads和它的工作没有任何问题。现在,我的问题是我的代码和你的代码之间有什么区别?(除了清楚之外)?他们正在做同样的事情,但我的不起作用。看看“我添加了条件变量”这句话会很有趣在代码中表示。条件变量始终表示关联的互斥,因此它也意味着内存障碍。关于障碍的相关性,请参阅我在上文中对原子操作重新排序的评论。在对OP的自我应答更新的修改中:在这种情况下,仍然要避免手动内存管理、共享全局变量和魔旗(我认为完成标志被打破了):。在这种情况下,仍然要避免手动内存管理、共享全局文件、魔术标志(我认为完成标志被打破了):
#include <boost/atomic.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <iostream>
#include <vector>

namespace /*static*/ {
  boost::atomic<int> data;

  boost::barrier*           slave_thread_finished_barrier;
  boost::mutex              slave_thread_finished_mutex; 
  boost::condition_variable slave_thread_finished_cond;
  bool                      slave_thread_finished = false;

  struct Work {
    void signal_slave()
    {
      boost::lock_guard<boost::mutex> lock(data_ready_mutex);
      data_ready = true;
      cond.notify_all();
    }

    void slave_thread()
    {
      static boost::atomic_int _id_gen(0);
      id = _id_gen++;

      std::cout << "(" << id << ") slave_thread created\n";
      while (true) {

        boost::unique_lock<boost::mutex> lock(data_ready_mutex);
        cond.wait(lock, [&]{ return data_ready; });

        data_ready = false;

        data++;

        num_run++;

        slave_thread_finished_barrier->wait();

        // signaling the main thread that the slave threads are done.
        if (id == 0)
        {
          boost::lock_guard<boost::mutex> lock(slave_thread_finished_mutex);
          slave_thread_finished = true;
          slave_thread_finished_cond.notify_one();
        }

      }
    }

  private:
    int id = 0;
    bool data_ready = false;
    int  num_run = 0;

    boost::mutex data_ready_mutex;
    boost::condition_variable cond;

  };

}

#include <boost/chrono.hpp>
#include <boost/chrono/chrono_io.hpp>

using hrc = boost::chrono::high_resolution_clock;

int main()
{
  boost::thread_group tg;

  size_t nThreads = 10;

  slave_thread_finished_barrier = new boost::barrier(nThreads);
  std::vector<Work> works(nThreads);

  for (size_t i = 0; i < nThreads; i++) {
    tg.create_thread(boost::bind(&Work::slave_thread, boost::ref(works[i])));
  }

  while (true) {
    auto start_time = hrc::now();

    for (auto& w : works)
      w.signal_slave();

    // Wait for slave threads to finish.
    boost::unique_lock<boost::mutex> lock(slave_thread_finished_mutex);
    slave_thread_finished_cond.wait(lock, [&]{ return slave_thread_finished; });
    slave_thread_finished = false;

    std::cout << "Elapsed Time = " << (hrc::now() - start_time) << std::endl;
  }

  tg.join_all();
}