线程本地存储(Thread Local Storage, TLS)(2)ThreadStaticAttribute
申明了 ThreadStaticAttribute
特性的静态变量,会被.NET 作为线程独享的数据来使用。
示例代码
ThreadStaticSample.cs
cs
using System;
using System.Threading;
namespace ThreadStaticSample
{
class ThreadStaticSample
{
/// <summary>
/// 值类型的线程静态数据
/// </summary>
[ThreadStatic]
static int _threadid = 0;
/// <summary>
/// 引用类型的线程静态数据
/// </summary>
static Ref _refthreadid = new Ref();
public static void DoWork()
{
_threadid = Thread.CurrentThread.ManagedThreadId;
_refthreadid._id = Thread.CurrentThread.ManagedThreadId;
Console.WriteLine("[{0}线程]:线程静态变量:{1},线程静态引用变量:{2}",
Thread.CurrentThread.ManagedThreadId.ToString(),
_threadid,
_refthreadid._id);
Thread.Sleep(1000);
Console.WriteLine("[{0}线程]:线程静态变量:{1},线程静态引用变量:{2}",
Thread.CurrentThread.ManagedThreadId.ToString(),
_threadid,
_refthreadid._id);
}
}
}
Ref.cs
cs
namespace ThreadStaticSample
{
/// <summary>
/// 简单引用类型
/// </summary>
class Ref
{
public int _id;
}
}
Program.cs
cs
using System;
using System.Threading;
namespace ThreadStaticSample
{
class Program
{
static void Main(string args)
{
Console.WriteLine("现在开始测试线程静态字段");
// 开辟 5 个线程来同时运行
// 这里不适合用线程池,
// 因为线程池内的线程会被反复使用,
// 导致线程 ID 一致
for (int i = 0; i < 5; i++)
{
Thread thread = new Thread(ThreadStaticSample.DoWork);
thread.Start();
}
Console.Read();
}
}
}
输出结果
现在开始测试线程静态字段
[3线程]:线程静态变量:3,线程静态引用变量:3
[5线程]:线程静态变量:5,线程静态引用变量:5
[7线程]:线程静态变量:7,线程静态引用变量:7
[6线程]:线程静态变量:6,线程静态引用变量:6
[4线程]:线程静态变量:4,线程静态引用变量:4
[7线程]:线程静态变量:7,线程静态引用变量:4
[3线程]:线程静态变量:3,线程静态引用变量:4
[5线程]:线程静态变量:5,线程静态引用变量:4
[4线程]:线程静态变量:4,线程静态引用变量:4
[6线程]:线程静态变量:6,线程静态引用变量:4
运行时发现一个奇怪的现象,对 _refthreadid
变量追加 [ThreadStatic]
特性后,运行会出 NullReferenceException
异常。
修改后的 ThreadStaticSample.cs
cs
using System;
using System.Threading;
namespace ThreadStaticSample
{
class ThreadStaticSample
{
/// <summary>
/// 值类型的线程静态数据
/// </summary>
[ThreadStatic]
static int _threadid = 0;
/// <summary>
/// 引用类型的线程静态数据
/// </summary>
[ThreadStatic]
static Ref _refthreadid = new Ref();
public static void DoWork()
{
_threadid = Thread.CurrentThread.ManagedThreadId;
if (_refthreadid == null)
{
_refthreadid = new Ref();
}
_refthreadid._id = Thread.CurrentThread.ManagedThreadId;
Console.WriteLine("[{0}线程]:线程静态变量:{1},线程静态引用变量:{2}",
Thread.CurrentThread.ManagedThreadId.ToString(),
_threadid,
_refthreadid._id);
Thread.Sleep(1000);
Console.WriteLine("[{0}线程]:线程静态变量:{1},线程静态引用变量:{2}",
Thread.CurrentThread.ManagedThreadId.ToString(),
_threadid,
_refthreadid._id);
}
}
}
输出结果
现在开始测试线程静态字段
[3线程]:线程静态变量:3,线程静态引用变量:3
[5线程]:线程静态变量:5,线程静态引用变量:5
[7线程]:线程静态变量:7,线程静态引用变量:7
[6线程]:线程静态变量:6,线程静态引用变量:6
[4线程]:线程静态变量:4,线程静态引用变量:4
[3线程]:线程静态变量:3,线程静态引用变量:3
[7线程]:线程静态变量:7,线程静态引用变量:7
[4线程]:线程静态变量:4,线程静态引用变量:4
[5线程]:线程静态变量:5,线程静态引用变量:5
[6线程]:线程静态变量:6,线程静态引用变量:6