C++ 如何正确地结束一根线?

C++ 如何正确地结束一根线?,c++,multithreading,synchronization,C++,Multithreading,Synchronization,我的主程序创建了一个线程。该线程初始化一些数据,然后进入“while”循环并运行,直到主程序将控制变量设置为“false”。然后它调用join()witch,无限地阻止整个代码 bool m_ThreadMayRun; void main(){ thread mythread = thread(&ThreadFunction); //do stuff m_ThreadMayRun = false; mythread.join(); // this blocks

我的主程序创建了一个线程。该线程初始化一些数据,然后进入“while”循环并运行,直到主程序将控制变量设置为“false”。然后它调用join()witch,无限地阻止整个代码

bool m_ThreadMayRun;

void main(){
   thread mythread = thread(&ThreadFunction);
   //do stuff
   m_ThreadMayRun = false;
   mythread.join(); // this blocks endlessly even when I ask 'joinable' before
}

void ThreadFunction{
   initdata();
   m_ThreadMayRun=true;
   while(m_ThreadMayRun){
   //do stuff that can be / has to be done for ever
   }
   deinitdata();
}
  • 我是不是遗漏了什么
  • 让循环离开主线程的正确解决方案是什么
  • 有必要叫join吗

感谢您的帮助

对于写入
m_ThreadMayRun
的两个线程,您有一个争用条件。考虑一下如果主线程执行<代码> MythRead MyLun= false,会发生什么情况?code>然后,您希望的线程执行
m_ThreadMayRun=true,则有一个无限循环。然而,严格地说,这条推理路线是不相关的,因为当您有一个竞争条件时,您的代码具有未定义的行为

我是不是遗漏了什么

您需要通过使
std::atomic
或使用
std::mutex
同步对
m_ThreadMayRun=false
的访问,并确保在
m_ThreadMayRun=true之后执行
m_ThreadMayRun=false


PS对于这种情况,最好使用
std::condition\u变量

您有一个两个线程写入
m\u ThreadMayRun
的争用条件。考虑一下如果主线程执行<代码> MythRead MyLun= false,会发生什么情况?code>然后,您希望的线程执行
m_ThreadMayRun=true,则有一个无限循环。然而,严格地说,这条推理路线是不相关的,因为当您有一个竞争条件时,您的代码具有未定义的行为

我是不是遗漏了什么

您需要通过使
std::atomic
或使用
std::mutex
同步对
m_ThreadMayRun=false
的访问,并确保在
m_ThreadMayRun=true之后执行
m_ThreadMayRun=false


PS在这种情况下,最好使用
std::condition_变量

问题是对
bool m_线程的访问可能会运行不同步,根据C++规则,每个线程可能假设线程之间没有改变。所以你最终会有一场比赛(一种未定义的行为)

要明确意图,请将其设置为原子的

std::atomic<bool> m_ThreadMayRun;

有关内存限制和获取/释放语义的更多详细信息,请参阅以下优秀资源:《C++并发操作》一书和Herb Sutter的演讲。

问题在于,访问布尔m_线程可能会运行不同步,根据C++规则,每个线程可能假设线程之间没有改变。所以你最终会有一场比赛(一种未定义的行为)

要明确意图,请将其设置为原子的

std::atomic<bool> m_ThreadMayRun;

有关内存隔离和获取/释放语义的更多详细信息,请参阅以下优秀资源:《C++并发操作》一书和Herb Sutter的演讲。

在这里最好使用condvar,以确保
m_ThreadMayRun=true
m_ThreadMayRun=false
@user3365922确实,我想让它保持简单,但我将添加一个注释在主线程中将控制变量设置为true是一种清晰易懂的风格改进。但是在这之后,因为线程只读取变量,所以我看不到竞争条件。我瞎了吗?但如果“原子”是关键,我对这个解决方案很满意。@M.Enke有
M_ThreadMayRun=true在从代码中的线程调用的函数中。即使线程只读取,也会有问题。当两个线程访问同一个内存并且至少有一个线程写入它时,就会出现一个争用条件。最好在这里使用condvar来确保
m_ThreadMayRun=true
m_ThreadMayRun=false
@user3365922之后执行
,但是我将添加一个注释在主线程中将控制变量设置为true是一种清晰易懂的风格改进。但是在这之后,因为线程只读取变量,所以我看不到竞争条件。我瞎了吗?但如果“原子”是关键,我对这个解决方案很满意。@M.Enke有
M_ThreadMayRun=true在从代码中的线程调用的函数中。即使线程只读取,也会有问题。当两个线程访问同一内存,并且至少有一个线程写入ITA时,就会出现争用情况,正如您所看到的
joinable()
在这里没有帮助。螺纹是可接合的;你就是这样创造的。(顺便说一句,创建线程可以(而且应该)使用
线程我的线程(&ThreadFunction)
)完成,正如您所看到的
可连接()
在这里没有帮助。螺纹是可接合的;你就是这样创造的。(顺便说一句,创建线程可以(也应该)使用
线程我的线程(&ThreadFunction)