VB.NET并行与分布式编程(6)-线程与内核同步[2]
那么我们通过关键区域可以解决这个问题吗
Thread.BeginCriticalRegion 通知宿主执行将要进入一个代码区域,在该代码区域内线程中止或未经处理的异常的影响可能会危害应用程序域中的其他任务。公共语言运行时 (CLR) 的宿主(如 Microsoft SQL Server 2005)可以对关键和非关键代码区域建立不同的失败策略。 关键区域是指线程中止或未经处理的异常的影响可能不限于当前任务的区域。 相反,非关键代码区域中的中止或失败只对出现错误的任务有影响。
我们将减法部分与输出计算结果部分纳入关键区域
Imports System Imports System.Threading Imports System.Diagnostics Imports System.Diagnostics.ThreadState 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) mythread1.Name = "thread_1" mythread2.Name = "thread_2" mythread3.Name = "thread_3" '设置线程是否允许动态优先级 Console.WriteLine(Now.ToLongTimeString & "线程对象创建完毕,开始执行线程") Dim myprocess As Process = Process.GetCurrentProcess() Console.WriteLine("进程名称:" & myprocess.ProcessName) '执行线程 mythread1.Start(myprocess) mythread2.Start(myprocess) mythread3.Start(myprocess) '等待线程完成 mythread1.Join() mythread2.Join() mythread3.Join() '线程执行完毕 Console.WriteLine(Now.ToLongTimeString & "线程执行完毕!") End Sub Public Sub mythreadrun(ByVal myprocess As Object) Dim mynum As Double Static Dim jg As Double = 100 Try For mynum = 1 To 2 Step 0.1 Thread.BeginCriticalRegion() jg -= mynum Console.WriteLine(Thread.CurrentThread.Name & "==>" & Now.ToLongTimeString & "=>" & (jg + mynum) & "-" & mynum & ",计算结果为:" & jg) Thread.EndCriticalRegion() Next Catch Console.WriteLine(Thread.CurrentThread.Name & " " & Now.ToLongTimeString & "线程异常终止!") '终止线程 Thread.CurrentThread.Abort() Finally Console.WriteLine(Thread.CurrentThread.Name & "优先级: " & Thread.CurrentThread.Priority.ToString) Console.WriteLine(Thread.CurrentThread.Name & " " & Now.ToLongTimeString & "线程运行完毕!") End Try End Sub End Module
结果证明没有效果,单纯的关键区域(临界域)解决不了这种数据同步问题
其关健在于要解决对数据本身锁的问题,由此我们引入互斥体,互斥体是一个仅用于实现同步的内核对象,目的是构建拥有互斥行为的临界域(即前面所说的关键区域)
Imports System Imports System.Threading Imports System.Diagnostics Imports System.Diagnostics.ThreadState 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) mythread1.Name = "thread_1" mythread2.Name = "thread_2" mythread3.Name = "thread_3" '设置线程是否允许动态优先级 Console.WriteLine(Now.ToLongTimeString & "线程对象创建完毕,开始执行线程") Dim myprocess As Process = Process.GetCurrentProcess() Console.WriteLine("进程名称:" & myprocess.ProcessName) '执行线程 mythread1.Start(myprocess) mythread2.Start(myprocess) mythread3.Start(myprocess) '等待线程完成 mythread1.Join() mythread2.Join() mythread3.Join() '线程执行完毕 Console.WriteLine(Now.ToLongTimeString & "线程执行完毕!") End Sub Public Sub mythreadrun(ByVal myprocess As Object) Dim mynum As Double Static Dim mymutex As New Mutex Static Dim jg As Double = 100 Try For mynum = 1 To 10 Thread.BeginCriticalRegion() mymutex.WaitOne() jg -= mynum Console.WriteLine(Thread.CurrentThread.Name & "==>" & Now.ToLongTimeString & "=>" & (jg + mynum) & "-" & mynum & ",计算结果为:" & jg) Thread.EndCriticalRegion() Thread.Sleep(0) mymutex.ReleaseMutex() Next Catch Console.WriteLine(Thread.CurrentThread.Name & " " & Now.ToLongTimeString & "线程异常终止!") '终止线程 Thread.CurrentThread.Abort() Finally 'mymutex.Close() Console.WriteLine(Thread.CurrentThread.Name & "优先级: " & Thread.CurrentThread.Priority.ToString) Console.WriteLine(Thread.CurrentThread.Name & " " & Now.ToLongTimeString & "线程运行完毕!") End Try End Sub End Module
上述代码的重点在于:
首先在工作线程中,声明一个静态互斥体,这样多个线程可以共享一个互斥体
Static Dim mymutex As New Mutex
然后,通过 Mutex.WaitOne()方法等待互斥体被释放,使用完变量jg后,释放互斥体,允许其它线程对jg进行操作
Try
For mynum = 1 To 10
Thread.BeginCriticalRegion()
mymutex.WaitOne()
jg -= mynum
Console.WriteLine(Thread.CurrentThread.Name & "==>" & Now.ToLongTimeString & "=>" & (jg + mynum) & "-" & mynum & ",计算结果为:" & jg)
Thread.EndCriticalRegion()
Thread.Sleep(0)
mymutex.ReleaseMutex()
可以看到通过引入互斥体,同步问题得到了解决