线程本地存储(Thread Local Storage, TLS)(1)线程数据插槽
所谓的线程本地存储(TLS),是指存储在线程环境块内的一个结构,用了存放该线程内独享的数据。
进程内的线程不能访问不属于自己的 TLS,这就保证了 TLS 内的数据在线程内是全局共享的,而对线程外却是不可见的。
.NET 提供了简单的机制供程序员使用本地存储,定义在 System.Threading.Thread
类型内的 AllocateDataSlot
和 AllocateNamedDataSlot
方法提供一个存储在所有线程内的数据插槽,而通过这个插槽结构,程序员可以使用下列两个方法来存取线程独享的数据,这两个方法都定义在 System.Threading.Thread
类型中。
cs
//
// 摘要:
// 在当前线程的当前域中从当前线程上指定的槽中检索值。为了获得更好的性能,请改用以 System.ThreadStaticAttribute 特性标记的字段。
//
// 参数:
// slot:
// 要从其中获取值的 System.LocalDataStoreSlot。
//
// 返回结果:
// 检索到的值。
public static object GetData(LocalDataStoreSlot slot);
//
// 摘要:
// 在当前正在运行的线程上为此线程的当前域在指定槽中设置数据。为了获得更好的性能,请改用以 System.ThreadStaticAttribute 特性标记的字段。
//
// 参数:
// slot:
// 在其中设置值的 System.LocalDataStoreSlot。
//
// data:
// 要设置的值。
public static void SetData(LocalDataStoreSlot slot, object data);
示例代码
ThreadDataSlot.cs
cs
using System;
using System.Threading;
namespace ThreadDataSlot
{
class ThreadDataSlot
{
/// <summary>
/// 分配一个数据插槽,注意插槽本身是全局可见的
/// 因为这里的分配是在所有线程的 TLS 内建立数据块
/// </summary>
static LocalDataStoreSlot _localSlot = Thread.AllocateDataSlot();
/// <summary>
/// 线程方法,操作数据插槽来存放数据
/// </summary>
public static void DoWork()
{
// 这里把线程 ID 存放在数据插槽内
// 一个应用程序内线程 ID 不会重复
Thread.SetData(_localSlot, Thread.CurrentThread.ManagedThreadId);
// 查看一下刚刚插入的数据
Console.WriteLine("线程{0}内的数据是:{1}",
Thread.CurrentThread.ManagedThreadId.ToString(),
Thread.GetData(_localSlot).ToString());
// 线程睡眠 1 秒
Thread.Sleep(1000);
// 查看其它线程的运行是否干扰了当前线程数据插槽内的数据
Console.WriteLine("线程{0}内的数据是:{1}",
Thread.CurrentThread.ManagedThreadId.ToString(),
Thread.GetData(_localSlot).ToString());
}
}
}
Program.cs
cs
using System;
using System.Threading;
namespace ThreadDataSlot
{
class Program
{
static void Main(string args)
{
Console.WriteLine("现在开始测试数据插槽");
// 开辟 5 个线程来同时运行
// 这里不适合用线程池,
// 因为线程池内的线程会被反复使用,
// 导致线程 ID 一致
for (int i = 0; i < 5; i++)
{
Thread thread = new Thread(ThreadDataSlot.DoWork);
thread.Start();
}
Console.Read();
}
}
}