13

使用类名访问静态字段,如下所示:

public class Me()
{ 
  public static int a=5;
}

我可以使用 访问它Me.a,因此它附加到

但是当我看:

static ThreadLocal<int> _x = new ThreadLocal<int> (() => 3);

它保证每个线程看到不同的_x.

我们不是只看到static每个而不是每个线程吗?如何ThreadLocal设法给每个线程一个不同的副本_x

4

3 回答 3

12

我们不是刚刚看到静态是每个类而不是每个线程吗?

是的。所以想象一个ThreadLocal<T>实例持有一个static Dictionary<Thread, T>查找当前线程的值的实例。

这可能不是它实际工作的方式,但它是对它如何可能的简单解释。你可以自己写。

所以你仍然只有 1 个 static _x。但_x.Value可以绑定到任何东西,比如当前线程。

于 2012-07-21T11:44:37.100 回答
8

根据其说明符,该引用_x确实是每个类一个static。但是,只有引用将在所有线程之间共享,而不是其对象内的值。当您访问 时_x.ValueThreadLocal<T>调用在当前线程上提供存储的系统特定代码,并读取或写入该线程特定存储。

于 2012-07-21T11:42:39.570 回答
4

我的 C# 不是那么好,所以这里有一个相同效果的 C++ 答案:想象一个包含一个大数组的假设类:

class Foo
{
    int array[HUGE];
    int & get() { return array[this_thread_id()]; }
}:

现在您可以拥有一个单一的全局(或类静态)对象:

Foo tlstorage;

从您所说的任何地方访问它tlstorage.get() = 12;。但是,数据存储在“属于”当前线程的插槽中。整个存储是全局的,但每个线程只暴露一个切片

其他语言(如 C 和 C++)对这个概念有本机支持,当您将全局或静态变量装饰为“线程局部”时,编译器会自动构建相当于相同效果的东西。也许在 C# 中,这是一个库功能,尽管它也可能映射到一些内在的东西。

于 2012-07-21T11:45:14.590 回答