C++ Boost线程条件变量三线程
我有一个main设置两个变量的值,并等待两个线程打印该值。然后更新值等等 对于主线程和一个线程,它可以工作,但对于两个线程则不行。 这是我的代码:C++ Boost线程条件变量三线程,c++,boost,C++,Boost,我有一个main设置两个变量的值,并等待两个线程打印该值。然后更新值等等 对于主线程和一个线程,它可以工作,但对于两个线程则不行。 这是我的代码: void t(int id){ bool block_me = true; while(1) { { boost::mutex::scoped_lock lock(m); while(!start_t || thread_executed > 0)
void t(int id){
bool block_me = true;
while(1)
{
{
boost::mutex::scoped_lock lock(m);
while(!start_t || thread_executed > 0)
start_thread.wait(lock);
}
// Print myself
cout<<id<<endl;
{
boost::mutex::scoped_lock lock(m);
thread_executed++;
if(thread_executed == 2){
start_main.notify_one();
}
}
}
}
int main(){
thread_executed = 0;
start_t = false;
boost::thread t1(boost::bind(&t, 1));
boost::thread t2(boost::bind(&t, 2));
for(int i = 1; i < 10; i++){
cout<<"i = "<<i<<endl;
{
boost::mutex::scoped_lock lock(m);
start_t = true;
thread_executed = 0;
start_thread.notify_all();
while(thread_executed != 2){
start_main.wait(lock);
}
start_t = false;
thread_executed = 0;
start_thread.notify_all();
}
}
return 0;
}
void t(int-id){
bool block_me=true;
而(1)
{
{
boost::mutex::作用域锁定(m);
而(!start_t| | thread_executed>0)
启动线程。等待(锁定);
}
//打印我自己
cout这里最可能发生的情况是,第一个线程运行并更改变量“published”,然后坐着等待,第二个线程只是坐着等待published再次变为0,但情况永远不会是这样,因为主线程正在等待它变为2以将其变回0
为了以有效的方式实施,可以做的事情很少:
让线程将您需要打印的内容排队,然后另一个线程将从队列中取出并打印它们(或将它们写入磁盘,或任何您真正需要使用它们的操作)。这是一种非常常见的模式,可以简化总体实施。可能会有成本,然后您可能无法以这种方式实施
将“状态”添加到线程中,这样当您处于“打印”状态时,线程将被唤醒并打印值;当您处于“处理”状态时,线程将在条件变量中等待,主线程将“处理”值。在更改状态之前,您可以使用等待,直到所有互斥体完成其工作
有几点建议:
- 如果在线程中读取变量“published”和“termiante_thread”,则不要在互斥保护之外更改变量。例如,当您更改变量以停止线程时,需要保护变量“published”和“termiante_thread”
- 不要使用睡眠,您不需要它们来实现一个工作示例,它们是实现中出现问题的征兆
我修改了我的原始代码…嗯,排队等待
让我们来演示一下
我稍微概括了一下,因为基本上有两个带有共享条件变量的单元素队列
更容易推理的是两个具有不同条件和锁的独立队列。这会立即解开它们以进行同步,如果将容量定义为>1,则在主线程需要减速之前,工作线程可能会有多个积压的项目排队
#include <thread>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <iostream>
static constexpr size_t queue_capacity = 1;
struct Processor {
Processor(int id) : id_(id) {}
void work() {
while (running) {
int value;
{ // pop under lock
std::unique_lock<std::mutex> lk(mx_);
cv_.wait(lk, [this] { return !running || !queue_.empty(); });
if (!running)
break;
// invariant: queue cannot be empty here
value = queue_.front();
queue_.pop();
cv_.notify_one();
}
std::cout << "work " << id_ << ": " << value << "\n";
}
}
void enqueue(int value) {
std::unique_lock<std::mutex> lk(mx_);
cv_.wait(lk, [this] { return !running || queue_.size() < queue_capacity; });
if (running) {
queue_.push(value);
cv_.notify_one();
}
}
~Processor() {
{
std::unique_lock<std::mutex> lk(mx_);
cv_.notify_one();
running = false;
}
if (th_.joinable())
th_.join();
}
private:
bool running = true;
std::mutex mx_;
std::condition_variable cv_;
std::thread th_ {std::bind(&Processor::work, this)};
int id_;
std::queue<int> queue_;
};
int main() {
Processor w1(1), w2(2);
for (int i = 1; i < 10; ++i)
{
w1.enqueue(i*10);
w2.enqueue(i*20);
std::this_thread::sleep_for(std::chrono::milliseconds(150));
}
std::this_thread::sleep_for(std::chrono::seconds(4));
}
如果要向生产者发回信号,则需要第二个条件变量。此外,access*仅在锁下访问所有共享变量(您违反了该左和右键)看起来像是在寻找一个我不知道的…我需要线程启动simpe打印的条件和main更改“一”和“二”"…你考虑过使用消息队列吗?我已经修改了我的原始代码…嗯,队列为??我已经修改了我的原始代码…但是,没有使用boost barrier的解决方案吗?是的,使用barrier只是一种方法,你可以看看给出的答案之一,它显示了如何使用队列来完成任务,而不使用barriers
work work 1: 10
2: 20
work work 2: 40
1: 20
work 2: 60
work 1: 30
work 2: 80
work 1: 40
work 2: 100
work 1: 50
work 2: 120
work 1: 60
work 2: 140
work 1: 70
work 2: 160
work 1: 80
work 2: 180
work 1: 90