线程不应该访问其他线程的堆栈有什么原因吗?
Is there a reason a thread shouldn't access other thread's stack?
我刚刚在我的项目中使用英特尔并行检查器,它显示一条警告:
应用程序中的一个或多个线程访问了另一个线程的堆栈 线。这可能表示应用程序中存在一个或多个错误。
我确实有一些对象是在线程之间共享的堆栈上分配的。我不明白为什么这是一个问题。有什么提示吗?
这没有错,只是可能是错的。 像英特尔并行检查器这样的工具为您的程序提供额外的诊断,必须在误报和漏报之间进行权衡,在这种情况下,开发人员似乎认为访问另一个线程的堆栈更有可能是错误(如果报告,则误报率低)而不是不错误(如果未报告,则为高误报率)。
Valgrind 是另一个工具的例子,它可以在正确的代码中发出错误的信号。
这里真正的问题是,"另一个线程在做什么? 如果你认为,"也许它会从该函数返回,堆栈帧将无效",那么你做错了并行编程。 关于多线程行为的任何答案都不应该用"也许"来限定。 您最好确保该线程不会返回,例如,通过使其等待信号量或条件变量,或者使其与其他线程联接。
讨论
Pubby:"AFAIK效率非常低。
它效率低下的唯一原因是,您可能有多个内核修改相同的缓存行,这与其他类型的共享内存遇到的问题相同。
Collin:你怎么知道堆栈帧在另一个线程中仍然很好?
如果在多个线程中使用某些内容,则可以使用某种同步机制来确保不会以无效的方式对其进行修改。 这种情况也不例外。
H2CO3:嗯,有没有理由你不应该走进别人的房子?
如果我们要玩类比,我会说过程就是房子,每个线程都是房子里的人。 如果戴夫在他的房间里保留了一份家务清单,那么每次我需要看清单时,我都会去他的房间。 如果他停止这样做,他最好告诉我,否则我会开始在他桌子上的随机纸上写字。
结论
此程序行为是否可以接受是一个风格问题。
想象一下 - 一个线程正在执行,并且调用了一个具有局部(堆栈)变量(对象)的方法。它将此对象添加到工作队列中,该队列由单独的线程处理。
该线程访问第一个线程添加的项,并访问第一个线程的堆栈上的对象。
在此期间,第一个线程做了什么? 它可能已退出该方法并释放了该堆栈空间。释放的空间可能会也可能不会重复使用。 访问第一个线程堆栈的第二个线程可能会也可能不会正常工作,具体取决于时间和调用图。
如果您知道堆栈变量在第二个线程处理它时将存在,那么这样做是安全的;例如,如果线程 1 将堆栈变量排队,然后阻塞直到线程 2 通知它已完成处理,这是一个安全的操作。
发出警告而不是错误是因为这可能是也可能不是合法操作,并且分析器无法确定。
- 线程,如果else语句,都是错误的上下文切换后,会发生什么
- 是什么导致了Unity 3D中的"错误线程异常"?
- 我的C++线程做错了什么?
- 处理影响跨不同线程共享对象的定时回调的最佳方法是什么?
- 正在连接的等待条件变量的线程会发生什么情况?
- 线程和互斥锁的使用有什么问题
- 等待线程的最佳方式是什么
- 调用boost.asio的异步函数时,线程是什么时候创建的
- 什么是运行英特尔线程构建模块的 XCode 8 环境变量
- 在 C++11 线程中,std::mutex 对内存可见性有什么保证?
- 什么时候标准::线程::连接会因no_such_process而失败
- 当两个线程同时尝试在同一静音上尝试try_lock()时会发生什么
- 什么时候使用互斥锁的吸气剂和二传手是线程安全的?
- 在Qt中使用工作线程将数据写入文件的正确方法是什么?
- 什么保证两个不相关的线程中的不同不相关对象没有(不可避免的)争用条件?
- gdb 中的线程 0x7fffc57fa700 (LWP 31671) 退出] 是什么意思?
- 如果我将作品张贴到线程池,并且线程已经在Boost中工作,会发生什么
- 停止线程的方法是什么(当我直接从Qthread继承时)
- QTimer对象是否在单独的线程中运行?它的机制是什么
- 什么是线程锁返回代码值