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