我正在尝试创建一个多线程程序。它是一个非常简单的应用程序,我只是创建,以了解多线程如何工作等等:)
好吧所以事情是我有2个线程和1个变量,Thread1应该每隔一秒打印一次它们共有的变量(时间并不重要,只是一个例子)然后Thread1睡1第二个Thread2进来并将其值编辑为完全不同的东西,下一次Thread1运行它应该打印由thread2分配的新值,尽管这没有发生:/发生的事情是Thread1打印默认的构造函数值,即使它得到了改变了,用文字解释很难,所以我把下面简单的例子联系起来,我希望有人可以帮我理解这一点。顺便说一下,我知道我应该使用互斥或临界部分,因为我在两者之间共享资源,但由于它们从不同时运行而且它只是一个简单的例子我只是把它留了出来。
Main.cpp的
int _tmain(int argc, _TCHAR* argv[])
{
Printer printer;
std::thread thread1(&Printer::SetMessage, printer, printer); //Sets the new value of "New Message"
std::thread thread2(&Printer::Print, printer, &printer); //Prints the message using printf()
while(true) {
Sleep(5000); //i have a beakpoint here just to look at the variables once every 5 sec.
}
return 0;
}
Printer.cpp
void Printer::Print(Printer &obj) {
while(true) {
printf(obj.Message.c_str());
Sleep(1000);
}
}
void Printer::SetMessage(Printer &obj) {
while(true) {
Sleep(10000);
obj.Message = "New Message";
}
}
Printer::Printer(void){
this->Message = "YOLO";
}
Printer::~Printer(void){}
所以我只想让Message的值在所有其他线程中更新,我的意思是他们使用相同的对象并更改同一该死的对象中的值,但为什么它不会在线程之间保持更改?我很困惑:我只看过在同一个班级做过的例子,一旦我使用了多个班级,就会变得更加复杂(在我脑中)。
答案 0 :(得分:3)
您将printer
传递给线程构造函数,复制对象,因此每个线程都有不同的Printer
,不是相同的对象
实际上,你的代码甚至不应该编译,但Visual Studio中的std::thread
有一个允许这种情况发生的错误(并且忽略了你写的&printer
会传递指针的事实,并且Printer::print(Printer& obj)
没有指针。)
要传递对线程函数的引用,您需要使用std::ref
来包装对象,这会创建一个reference_wrapper<Printer>
,它将参数转发为对新线程的引用,而不是复制和传递复制到新线程:
std::thread thread2(&Printer::Print, std::ref(printer), std::ref(printer));
但是,即使您修复了这个问题,您的代码也会有未定义的行为,因为它是不安全的,并且无法使用互斥锁或原子操作来安全地执行更新,因此两个线程无法读取/写入相同的内存位置。
答案 1 :(得分:1)
顺便说一下,我知道我应该使用互斥锁或关键部分,因为我在两者之间共享资源,但由于它们从不同时运行而且只是一个简单的例子我只是把它留了出来。
也许您错过的是,即使您在每个方法中都放置了睡眠指令,希望每个线程只在另一个处于休眠状态时处于活动状态,但无法保证程序将以这种方式执行。 / p>
阻止线程而另一个处于活动状态的唯一安全方法是使用锁来协调它们。
您还应该通过引用传递数据。