gpt4 book ai didi

c++ mutex cout不打印所有内容

转载 作者:行者123 更新时间:2023-11-28 07:32:56 26 4
gpt4 key购买 nike

我正在创建一个线程管理类,我可以向其发布任务(函数 + 参数),该类将负责对它们进行线程处理。

这个问题与整个类(class)没有太大关系(我认为),但更多的是使用多线程时锁定共享资源的一般问题。这是代码:

主要测试文件:

#include <iostream>
#include <thread>
#include <vector>
#include "Ttask_1.h"
#include <mutex>

using namespace std;

bool quit=false;

void* square(void* n);
void* print(void* n);
mutex cout_mutex;
mutex res_mutex;

bool cout_locked=false;

vector<Ttask_1<void*,void*>*> tasks1;
vector<Ttask_1<void*,void*>*> tasks2;

void check_for_work(vector<void*> &vec,vector<Ttask_1<void*,void*>*> &tasks)
{
while(!quit)
{
if(tasks.size()!=0)
{
(*tasks[0]).run(vec);
tasks.erase(tasks.begin());
}
else
quit=true;
}
while(cout_locked){}
cout_locked=true;
cout<<"thread done"<<endl;
cout_locked=false;

}

int main(int argc, const char * argv[])
{
vector<void*> vec;
int n=5;
//int *n_p=&n;
//Ttask_1<void*,void*> task(&n,square);
tasks1.push_back(new Ttask_1<void*,void*>(&n,square,true));
tasks1.push_back(new Ttask_1<void*,void*>(&n,print,false));

tasks2.push_back(new Ttask_1<void*,void*>(&n,square,true));
tasks2.push_back(new Ttask_1<void*,void*>(&n,print,false));



thread Thread1(check_for_work,ref(vec),ref(tasks2));


thread Thread2(check_for_work,ref(vec),ref(tasks1));
//(&Ttask_1<int,int>::run,&task,ref(vec));
// task.run(vec,Thread);
Thread1.join();
Thread2.join();


int a;
cin>>a;
return 0;
}

void* print(void* n)
{
for(int i=0;i<*(int*)(n);i++)
{
while(cout_locked){}
cout_locked=true;
cout<<i<<endl;
cout_locked=false;
}
void* a;
return a;
}

void* square(void* n)
{

int res=(*(int*)n)*(*(int*)n);

while(cout_locked){}
cout_locked=true;
cout<<res<<endl;
cout_locked=false;

int *res_p=new int;
res_p=&res;
return res_p;
}

ttask_1 类:

#ifndef task_Test_Ttask_1_h
#define task_Test_Ttask_1_h
#include <vector>
#include <mutex>
using namespace std;

extern mutex res_mutex;

template <class type1, class ret>
class Ttask_1
{
public:
Ttask_1(type1 arg_in,ret(*func_p_in)(type1),bool result)
{
safe_result=result;
arg1=arg_in;
func_p=func_p_in;
}
void run(vector<void*> &res_vector)
{

ret res=(*func_p)(arg1);

if(safe_result)
{
void *res_p=&res;
res_mutex.lock();
res_vector.push_back(res_p);
res_mutex.unlock();
}
done=true;

}
bool is_done(){return done;}
private:
bool safe_result;
bool done=false;
type1 arg1;
ret(*func_p)(type1);
};

#endif

如您所见,在我看到互斥锁不起作用后,我在 cout 上实现了我自己的“锁定”功能。行为完全相同,所以这不是问题。

行为如下:

我希望在程序终止之前将数字 0、1、2、3、4、25 和字符串“thread done”全部打印两次。

然而,我经常(不总是,但经常)得到这样的输出:

25 0 1 2 3 4 thread done thread done

所以少了几个数字,我不知道是什么原因造成的。就像我说的,即使我更换我自己的

    while(cout_locked){}
cout_locked=true;

通过

    cout_mutex.locked();

    cout_locked=false;

通过

    cout_mutex.unlock()

没有任何变化。

任何帮助将不胜感激,谢谢

最佳答案

您的主要问题是 quit 是一个全局变量。一旦一个线程完成,另一个线程将不再做任何工作(这可能包括根本不做任何工作)。每个线程都需要一个 quit 样式的变量,或者只使用 size 检查作为 while 循环的条件。

您还在 run 函数内将局部变量的地址放入 vector 中,因此您的结果可能无法预测。为什么不让结果 vector 实际上是类型安全的?

也就是说,您的代码存在许多功能和惯用问题:

  • cout_locked 变量似乎只起作用,那里存在竞争条件 - 但我实际上不确定是否需要锁定 cout
  • 您将所有内容都视为 void*,从而丢弃了 C++ 提供的大量类型安全性(如果您愿意的话)。
  • 您将类内初始化与构造函数初始化混合在一起(为什么不在构造函数中也初始化 done)。
  • 通常更喜欢构造函数初始化列表而不是构造函数主体中的赋值,以防止先构造后赋值的性能影响。
  • 您从 vector 的开头删除,这是从 vector 中删除效率最低的位置。如果它表示在队列中,请根据您的需要使用 queuedeque
  • print 返回一个随机指针。如果您需要它返回 void*,至少让它始终返回 null (0)。

关于c++ mutex cout不打印所有内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17305216/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com