线程变量和局部变量有什么区别?

9

在我的线程中,我总是以“正常”的方式声明局部变量,例如:

procedure TMyThread.Execute ;

var
   i : integer ;

begin
i := 2 ;

等等,如果我这样声明它们:

procedure TMyThread.Execute ;

threadvar
   j : integer ;

begin
j := 2 ;

执行/代码生成/速度/线程安全性如何改变?


(注:已经保留了HTML标签,无需再次添加)

我从未见过在函数内声明 threadvar。那样会编译吗? - CodesInChaos
不允许在过程/函数内部声明threadvar,即您不能声明本地的threadvar变量。 - Bozzy
2个回答

20

首先,带有 threadvar 代码是无效的语法。一个 threadvar 需要具有单元作用域而不是本地作用域。

局部变量

每次调用函数(包括来自不同线程和可重入调用)都会导致该函数的局部变量的不同实例。

线程本地变量

线程本地变量对于进程中的每个线程都有单独的实例。变量的实例和线程之间存在一对一的映射关系。

讨论

如果您的过程不是可重入的,并且它是唯一引用变量的过程,则本地变量和 threadvar 之间没有语义差异 - 但是如果可以使用本地变量,则应该使用本地变量。

在性能方面,threadvar 比本地变量慢,甚至在 DLL 的上下文环境中可能无法工作。

我的建议是尽可能在可能的情况下使用本地变量。如果需要一个每个线程只有一个实例的全局范围变量,则使用 threadvar (或者在 DLL 中使用Thread Local Storage (TLS))。然而,这种需求很少见,并且线程本地变量有许多与真正的全局变量相同的缺点。


谢谢@David提供的语法指针。我对语法应该是什么有点模糊。我想我会把J称为SomeThread.j,但在线程的哪里声明它呢?虽然我仍然不能完全看到它们的用途。 - rossmcm
2
@ross 如果你不需要,就不要使用它们。栈分配的本地变量是圣杯。如果你能够用栈变量完成所有工作,那就很棒!! - David Heffernan
@david:一个非常简单的例子...? - rossmcm
@ross 我今天下午打算花时间从我的代码中尝试删除它们,因为它们经常会出问题。如果有一个受线程本地化益处的例子,我会发布它。 - David Heffernan
2
直到现在我才注意到,但我可以看出术语“线程本地变量”可以被解释为指特殊类型的本地变量。我会加连字符——“线程本地变量”——以强调“线程本地”是修饰“变量”,而不仅仅是“线程”修饰“本地变量”。 - Rob Kennedy
显示剩余5条评论

2
通过使用ThreadVar关键字,每个线程都被赋予了每个变量的单独实例,从而避免数据冲突,保持线程独立性。
此外,由于这些变量是本地的,因此您不需要在临界区保护您的ThreadVar变量。
最好的问候, Radu

但是在Execute方法中声明的普通局部变量肯定与其他线程中的局部变量是分离开的。 - rossmcm
@ross 是的,如果它们在语义上起作用,那么本地变量确实是最好的选择。此外,它们与对Execute的可重入调用是分离的,如果发生这种情况,就更好了。 - David Heffernan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接