线程本地存储

 (TLS) 可用于存储对线程和应用程序域唯一的数据。 .NET 提供了下面两种托管 TLS 使用方式:线程相对静态字段和数据槽。

  • 如果可以在编译时预测确切需求,请使用线程相对静态字段(Visual Basic 中的线程相对 Shared 字段)。 线程相对静态字段的性能最佳。 它们还支持编译时类型检查。

  • 如果只能在运行时发现实际需求,请使用数据槽。 数据槽使用起来比线程相对静态字段更慢、更加棘手。由于数据存储为类型 Object,因此使用前必须将它强制转换为正确类型。

 

实现线程本地存储最简单的方式是在静态字段上附加ThreadStatic特性:
        [ThreadStatic] static int _x;
这样,每一个线程都会得到一个_x的独立副本。
但是,[ThreadStatic]并不支持实例字段(它对实例字段并不会产生任何作用);此外,它也不适于和字段初始化器配合使用,因为它们仅仅会在调用静态构造器的线程上执行一次。如果一定要处理实例字段,或者需要使用非默认值,则更适合使用ThreadLocal<T> 。

 

ThreadLocal<T>类型,他的出现更大的简化了TLS的操作。ThreadLocal<T>类型和Lazy<T>惊人相似
ThreadLocal的值是延迟计算的:其中的工厂函数会在(每一个线程)第一次调用时计算实际的值。
ThreadLocal可以提供TLS中数据的默认值。

另外ThreadLocal是泛型类,而LocalDataStoreSlot不是

 

实现线程本地存储的方式是使用Thread类的GetData和SetData方法。这些方法会将数据存储在线程独有的“插槽”(slot)中。Thread.GetData负责读取线程独有的数据存储中读取数据,而Thread.SetData则向其中写入数据。这两个方法都需要使用LocalDataStoreSlot对象来获得这个插槽。所有的线程都可以获得相同的插槽,但是它们的值却是互相独立的。

数据槽分为下列两种类型:命名槽和未命名槽。 两种类型都是使用 LocalDataStoreSlot 结构实现。命名槽非常便捷,因为可以在需要时检索槽,具体操作是将它的名称传递给 GetNamedDataSlot 方法,而不用维护对未命名槽的引用。 不过,如果另一个组件对线程相对存储使用相同的名称,并且线程同时执行你的组件和另一个组件的代码,这两个组件可能会相互损坏数据。

posted @ 2020-08-19 19:34  yetsen  阅读(328)  评论(0编辑  收藏  举报