线程不应该访问其他线程的堆栈有什么原因吗?



我刚刚在我的项目中使用英特尔并行检查器,它显示一条警告:

应用程序中的一个或多个线程访问了另一个线程的堆栈 线。这可能表示应用程序中存在一个或多个错误。

我确实有一些对象是在线程之间共享的堆栈上分配的。我不明白为什么这是一个问题。有什么提示吗?

这没有错,只是可能是错的。 像英特尔并行检查器这样的工具为您的程序提供额外的诊断,必须在误报和漏报之间进行权衡,在这种情况下,开发人员似乎认为访问另一个线程的堆栈更有可能是错误(如果报告,则误报率低)而不是不错误(如果未报告,则为高误报率)。

Valgrind 是另一个工具的例子,它可以在正确的代码中发出错误的信号。

这里真正的问题是,"另一个线程在做什么? 如果你认为,"也许它会从该函数返回,堆栈帧将无效",那么你做错了并行编程。 关于多线程行为的任何答案都不应该用"也许"来限定。 您最好确保该线程不会返回,例如,通过使其等待信号量或条件变量,或者使其与其他线程联接。

讨论

Pubby:"AFAIK效率非常低。

它效率低下的唯一原因是,您可能有多个内核修改相同的缓存行,这与其他类型的共享内存遇到的问题相同。

Collin:你怎么知道堆栈帧在另一个线程中仍然很好?

如果在多个线程中使用某些内容,则可以使用某种同步机制来确保不会以无效的方式对其进行修改。 这种情况也不例外。

H2CO3:嗯,有没有理由你不应该走进别人的房子?

如果我们要玩类比,我会说过程就是房子,每个线程都是房子里的人。 如果戴夫在他的房间里保留了一份家务清单,那么每次我需要看清单时,我都会去他的房间。 如果他停止这样做,他最好告诉我,否则我会开始在他桌子上的随机纸上写字。

结论

此程序行为是否可以接受是一个风格问题。

想象一下 - 一个线程正在执行,并且调用了一个具有局部(堆栈)变量(对象)的方法。它将此对象添加到工作队列中,该队列由单独的线程处理。

该线程访问第一个线程

添加的项,并访问第一个线程的堆栈上的对象。

在此期间,第一个线程做了什么? 它可能已退出该方法并释放了该堆栈空间。释放的空间可能会也可能不会重复使用。 访问第一个线程堆栈的第二个线程可能会也可能不会正常工作,具体取决于时间和调用图。

如果您知道堆栈变量在第二个线程处理它

时将存在,那么这样做是安全的;例如,如果线程 1 将堆栈变量排队,然后阻塞直到线程 2 通知它已完成处理,这是一个安全的操作。

发出警告而不是错误是因为这可能是也可能不是合法操作,并且分析器无法确定。

相关内容

最新更新