首页 > Python基础教程 >
-
C#教程之 C#线程安全类型(2)
7、使用ThreadStatic特性
ThreadStatic特性是最简单的TLS使用,且只支持静态字段,只需要在字段上标记这个特性就可以了
using System; using System.Threading; namespace ConsoleApp1 { class Program { //TLS中的str变量 //可以看到,str静态字段在两个线程中都是独立存储的,互相不会被修改。 [ThreadStatic] static string str = "hehe"; static void Main(string[] args) { //另一个线程只会修改自己TLS中的hehe Thread th = new Thread(() => { str = "Mgen"; Display(); }); th.Start(); th.Join(); Display(); } static void Display() { Console.WriteLine("{0} {1}", Thread.CurrentThread.ManagedThreadId, str); } } }
8、使用命名的LocalDataStoreSlot类型
显然ThreadStatic特性只支持静态字段太受限制了。.NET线程类型中的LocalDataStoreSlot提供更好的TLS支持。我们先来看看命名的LocalDataStoreSlot类型,可以通过Thread.AllocateNamedDataSlot来分配一个命名的空间,通过Thread.FreeNamedDataSlot来销毁一个命名的空间。空间数据的获取和设置则通过Thread类型的GetData方法和SetData方法。
using System; using System.Threading; namespace ConsoleApp1 { class Program { static void Main(string[] args) { //创建Slot LocalDataStoreSlot slot = Thread.AllocateNamedDataSlot("slot"); //设置TLS中的值 Thread.SetData(slot, "hehe"); //修改TLS的线程 Thread th = new Thread(() => { Thread.SetData(slot, "Mgen"); Display(); }); th.Start(); th.Join(); Display(); //清除Slot Thread.FreeNamedDataSlot("slot"); } //显示TLS中Slot值 static void Display() { LocalDataStoreSlot dataslot = Thread.GetNamedDataSlot("slot"); Console.WriteLine("{0} {1}", Thread.CurrentThread.ManagedThreadId, Thread.GetData(dataslot)); } } }
9、使用未命名的LocalDataStoreSlot类型
线程同样支持未命名的LocalDataStoreSlot,未命名的LocalDataStoreSlot不需要手动清除,分配则需要Thread.AllocateDataSlot方法。注意由于未命名的LocalDataStoreSlot没有名称,因此无法使用Thread.GetNamedDataSlot方法,只能在多个线程中引用同一个LocalDataStoreSlot才可以对TLS空间进行操作,将上面的命名的LocalDataStoreSlot代码改成未命名的LocalDataStoreSlot执行
using System; using System.Threading; namespace ConsoleApp1 { class Program { //静态LocalDataStoreSlot变量 static LocalDataStoreSlot slot; static void Main(string[] args) { //创建Slot slot = Thread.AllocateDataSlot(); //设置TLS中的值 Thread.SetData(slot, "hehe"); //修改TLS的线程 Thread th = new Thread(() => { Thread.SetData(slot, "Mgen"); Display(); }); th.Start(); th.Join(); Display(); } //显示TLS中Slot值 static void Display() { Console.WriteLine("{0} {1}", Thread.CurrentThread.ManagedThreadId, Thread.GetData(slot)); } } }
10、使用.NET 4.0的ThreadLocal<T>类型
.NET 4.0在线程方面加入了很多东西,其中就包括ThreadLocal<T>类型,他的出现更大的简化了TLS的操作。ThreadLocal<T>类型和Lazy<T>惊人相似,构造函数参数是Func<T>用来创建对象(当然也可以理解成对象的默认值),然后用Value属性来得到或者设置这个对象。
ThreadLocal的操作或多或少有点像上面的未命名的LocalDataStoreSlot,但ThreadLocal感觉更简洁更好理解。
using System; using System.Threading; namespace ConsoleApp1 { class Program { static ThreadLocal<string> local; static void Main(string[] args) { //创建ThreadLocal并提供默认值 local = new ThreadLocal<string>(() => "hehe"); //修改TLS的线程 Thread th = new Thread(() => { local.Value = "Mgen"; Display(); }); th.Start(); th.Join(); Display(); } //显示TLS中数据值 static void Display() { Console.WriteLine("{0} {1}", Thread.CurrentThread.ManagedThreadId, local.Value); } } }