要同步线程间共享的实例变量,有一个很简单的技巧,这就是使用Interlocket类。该类包含有共享的Increment和Decrement方法,可以将修改变量和检查结果的操作结合成一个单一的操作。这样做是必需的,因为一个线程可以修改变量的值,在接着检查结果之前,它的运行时间就结束了。在该线程再次运行时,变量的值就有可能被其它的线程修改了。
例如下面的代码增加Instructors类的mPhotosProcessed实例级变量的值:
Interlocked.Increment(mPhotosProcessed)
Interlocked类还支持Exchange和CompareExchange的方法,它们的作用分别是设置变量为特定的值,或者在该变量等于某个值时才这样做。
使用线程本地存储
虽然在理想的情况下你的线程将使用私有的实例变量,不过在许多时候,当你的线程运行一个对象的方法,而该方法可能被其它的线程共享时,这样你的线程可能需要存储和接收它自己的真正私有数据。例如,当一个线程池中的线程监视一个MSMQ队列,并且需要取得队列中数据,然后存储下来作以后处理用时,就会出现这种情形。
在Windows操作系统中,每个线程都拥有自己的线程本地存储(thread local storage,TLS),以用来跟踪状态信息。方便的是,Thread类拥有一套方法,可方便地创建和维护TLS中的内存区域(该区域称为data slots)。
值得一提的是,Thread类拥有一个共享的AllocateNamedDataSlot方法,可以使用指定的名字为AppDomain中的所有线程创建一个新的data slot。该slot可以在随后通过使用SetData和GetData方法设置和读取。例如,假定有一个称为WorkerClass类执行一些处理活动,并且我们想创建一定数量的线程来执行该工作。以下的代码段为所有的线程创建了一个称为“ID”的data slot,然后通过objWorker实例的StartWork方法,执行相应数量的线程:
Dim dssSlot As LocalDataStoreSlot
Dim tNew As Thread
Dim objWorker As WorkerClass
dssSlot = Thread.AllocateNamedDataSlot("ID")
For i = 0 to intMaxThreads
tNew = New Thread(New ThreadStart(AddressOf objWorker.StartWork)
tNew.Start
Next
要注意的是由于所有的新线程将会共享objWorker上的实例变量,因此StartWorker方法和任何通过Start调用的方法将需要使用同步以防止对这些变量的同时访问。不过,如果每个线程需要它们自己的数据在方法间共享,它们可以将一个拷贝放到TLS的“ID”slot中,如下所示。
Public Sub Start()
Dim dssIDSlot As LocalDataStoreSlot
Dim myID As Integer
' Do other work
dssIDSlot = Thread.GetNamedDataSlot("ID")
Thread.SetData(dssIDSlot, myID)
Call NextProcess()
End Sub
Private Sub NextProcess()
Dim myID As Integer
Dim dssIDSlot As LocalDataStoreSlot
dssIDSlot = Thread.GetNamedDataSlot("ID")
myID = Thread.GetData(dssIDSlot)
' Do other work
End Sub
当NextProcess方法被调用时,数据可以再次通过使用Getdata由slot中读取。
再次提醒一下,上面提到的设计模式在需要时才使用。只有在你的设计是很复杂而且需要从多个线程中访问同样的对象时,你才需要使用TLS。
上一页 [1] [2] [3] [4] [5] [6] [7] 下一页