VB.NET并行与分布式编程(3)-线程局部存储TLS[2]
接上节,我们可以使用下面语句创建一个线程本地变量,利用静态TLS功能
Dim betterCounter As ThreadLocal(Of Integer) = New ThreadLocal(Of Integer)(Function() 1)
betterCounter的值初始化为1。在本程序中,jg被初始化为50,并定义成线程本地变量
Dim jg As ThreadLocal(Of Integer) = New ThreadLocal(Of Integer)(Function() 50)
然后,我们使用jg.Value 来读写这个本地变量的值
jg.Value -= mynum
三、动态TLS
Imports System Imports System.Threading Module Module1 Sub Main() Dim mythread1 As Thread Dim mythread2 As Thread Dim mythread3 As Thread '创建线程对象 mythread1 = New Thread(AddressOf mythreadrun) mythread2 = New Thread(AddressOf mythreadrun) mythread3 = New Thread(AddressOf mythreadrun) Console.WriteLine(Now.ToLongTimeString & "线程对象创建完毕,开始执行线程") '执行线程 mythread1.Start("线程1") mythread2.Start("线程2") mythread3.Start("线程3") '等待线程完成 mythread1.Join() mythread2.Join() mythread3.Join() '线程执行完毕 Console.WriteLine(Now.ToLongTimeString & "线程执行完毕!") End Sub Public Sub mythreadrun(ByVal data As Object) Dim mynum As Integer '分配一个新的槽,这个槽存放线程本地数据,槽名称 '必须唯一 Thread.AllocateNamedDataSlot(data) Dim jg As LocalDataStoreSlot jg = Thread.GetNamedDataSlot(data) Thread.SetData(jg, 100) Try For mynum = 1 To 10 Thread.SetData(jg, Thread.GetData(jg) - mynum) Console.WriteLine(data & " " & Now.ToLongTimeString & "=>" & (Thread.GetData(jg) + mynum) & "-" & mynum & ",计算结果为:" & Thread.GetData(jg)) Thread.Sleep(2) Next Catch Console.WriteLine(data & " " & Now.ToLongTimeString & "线程异常终止!") '终止线程 Thread.CurrentThread.Abort() Finally Thread.FreeNamedDataSlot(data) End Try End Sub End Module
运行结果如我们所愿,jg变量通过动态TLS提供的槽机制实现了线程本地变量
'分配一个新的槽,这个槽存放线程本地数据,槽名称为
'myjg,名称必须唯一
Thread.AllocateNamedDataSlot(data)
Dim jg As LocalDataStoreSlot
jg = Thread.GetNamedDataSlot(data)
Thread.SetData(jg, 100)
以上代码是关健,我们使用命名数据槽,当然,我们也可以使用未命名槽,因为未命名数据槽相对较简单,所以这里使用了命名数据槽,向大家演示一下其功能。
注意:
如果使用 AllocateNamedDataSlot 方法已分配已经存在的指定名称的槽,此方法会引发异常,且无法测试是否已分配某个槽。另外,使用此方法分配的数据槽必须使用 FreeNamedDataSlot 来释放。
本例中,我们分配槽使用下面语句
Thread.AllocateNamedDataSlot(data)
获取某个命名槽的引用,以便进行下一步操作
jg = Thread.GetNamedDataSlot(data)
Thread.SetData和Thread.GetData可写、读槽中数据
四、数据槽的值在线程或上下文对象之间不共享
LocalDataStoreSlot 结构可用作本地存储内存机制,线程和上下文可以使用此机制分别存储线程特定的数据和上下文特定的数据。 公共语言运行时在创建每个进程时给它分配一个多槽数据存储区数组。 线程或上下文调用各种函数在数据存储区中分配数据槽、在槽内存储和检索数据值、以及释放数据槽以便在线程或上下文过期后重新使用它。
对于每个线程或上下文,数据槽都是唯一的;它们的值在线程或上下文对象之间不共享。 数据槽可根据名称或根据索引号来分配。
我们可以从下面程序看出
Imports System Imports System.Threading Module Module1 Sub Main() Dim mythread1 As Thread Dim mythread2 As Thread Dim mythread3 As Thread Dim jg As LocalDataStoreSlot '创建线程对象 mythread1 = New Thread(AddressOf mythreadrun) mythread2 = New Thread(AddressOf mythreadrun) mythread3 = New Thread(AddressOf mythreadrun) Console.WriteLine(Now.ToLongTimeString & "线程对象创建完毕,开始执行线程") 'jg = Thread.AllocateNamedDataSlot("myjg") ' Thread.SetData(jg, 100) '执行线程 mythread1.Start("线程1") mythread2.Start("线程2") mythread3.Start("线程3") '等待线程完成 mythread1.Join() mythread2.Join() mythread3.Join() '线程执行完毕 Console.WriteLine(Now.ToLongTimeString & "线程执行完毕!") Thread.FreeNamedDataSlot("myjg") End Sub Public Sub mythreadrun(ByVal data As Object) Dim randomGenerator As New Random() Dim mynum As Integer '分配一个新的槽,这个槽存放线程本地数据,槽名称为 'myjg Dim jg As LocalDataStoreSlot Try jg = Thread.AllocateNamedDataSlot("myjg") Catch jg = Thread.GetNamedDataSlot("myjg") End Try Thread.SetData(jg, 100) Try For mynum = 1 To 10 Thread.SetData(jg, Thread.GetData(jg) - mynum) Console.WriteLine(data & " " & Now.ToLongTimeString & "=>" & (Thread.GetData(jg) + mynum) & "-" & mynum & ",计算结果为:" & Thread.GetData(jg)) Thread.Sleep(randomGenerator.Next(10, 200)) Next Catch Console.WriteLine(data & " " & Now.ToLongTimeString & "线程异常终止!") '终止线程 Thread.CurrentThread.Abort() End Try End Sub End Module
上一篇: C++-使用auto_ptr保证异常安全
下一篇: MFC对象与WIN32句柄的映射-TLS