论文部分内容阅读
摘 要分析了VB.NET语言线程与进程的关系,线程的优先级,多线程需要同步的原因和使用多线程的同步机制访问共享资源的实现方法。
关键词多线程;VB.NET;同步
进程(Process)是应用程序在内存环境中基本的执行单元,进程是有不同的地址空间且处在可执行状态中的应用程序。线程(Thread)是进程中某个单一的顺序控制流程,线程不能够单独执行,它必须运行在处于活动状态的应用程序进程中,同一个进程的多个线程共享相同的内存空间,并发执行的多个线程之间存在着对临界资源的争夺问题,即互相配合的几个线程之间如何实现工作点同步的问题。
一、线程的创建
VB.NET中的多线程功能主要是通过Thread类来支持和实现的。Thread类属于.NET基础类库的System.Threading命名空间。线程自创建后就处于其生命周期中,程序可以对线程进行各种控制操作,包括启动、挂起、休眠、恢复和停止等。①创建线程Dim myThread = New System. Threading.Thread(AddressOf过程名),把一个过程定义成一个新线程以便和其他线程并发执行;②启动线程 myThread.Start 使线程从就绪状态变为运行状态;③挂起线程 myThread.suspend() 使该线程从运行变为停止状态,直到再次恢复它为止;④使线程休眠 myThread.sleep(整数值);⑤恢复线程 myThread.resume() 该线程再次启动,继续工作。⑥停止线程 myThread.abort() 该线程停止工作,并被释放,不能再被恢复。
二、线程的优先级
线程的优先级代表线程的重要程度,当有多个线程同时处于可执行状态并等待获得CPU时间,线程调度器根据各个线程的优先级来决定给谁分配CPU时间,采用“抢占式”策略来调度线程执行,优先级越高获得CPU时间的机会就越大,如果优先级相同,则遵循“先来先服务”的调度原则。VB.net使用线程的Priority属性来设置线程的优先级。常用的优级别有:AboveNormal (较高优先级)、BelowNormal(较低优先级)、Highest(最高优先级)、Lowest(最低优先级)、Normal(平均优先级)。如果要指定线程myThread的优先级为最高优先级,则用语句myThread.Priority = ThreadPriority.Highest说明。
三、多线程同步
(一)多线程需要同步的原因
由于同一进程的多个线程共享同一片存储空间,在带来的方便的同时,也会带来访问冲突等问题。比如,两个线程同时存取一个数据变量,其中一个对数据进行了修改,而另一个线程仍旧是修改前的数据,这就带来了数据不一致的问题。例如在汽车售票过程中,可能会有很多人同时购票,必须开辟多个线程同时为他们服务,假设共有60张票,分别由4个线程完成。
Class Ticket
Dim tickets As Integer = 60 ’总票数
Sub run()
While True
’A点
If tickets > 0 Then
Thread.Sleep(10) ’当前执行的线程睡眠10毫秒
Console.Write( tickets & “ ”)
tickets -= 1
End If
’B点
End While
End Sub
End Class
Private Sub Button1_Click( ~)
Dim t1, t2, t3, t4 As Thread
Dim Tticket As New Ticket
t1 = New Thread(AddressOf Tticket.run):t2 = New Thread(AddressOf Tticket.run)
t3 = New Thread(AddressOf Tticket.run):t4 = New Thread(AddressOf Tticket.run)
t1.Start() : t2.Start() : t3.Start() : t4.Start()
End Sub
单击按钮运行结果如下:60,59,…,1,0,-1,-2, 从执行结果就可以看出为什么系统中票已卖完还可以继续卖几张的原因,就是因为当系统中只有一张票的时候,第一个线程都进入了if代码段里面,买了最后一张票, tickets为0,这时时间片到了;第二个线程开始运行,买了第0张票, tickets为-1,时间片到期了。以此类推,第三、第四个线程if代码段里面,从而导致了系统继续把0,-1,-2的票打印出来,这当然不是我们想要的结果,这种结果是不正确的,这个问题的根源在于多个线程同时访问了tickets变量,单独的并发的线程访问代码段中的同一对象(tickets),则这个代码段叫做临界区,我们需要用同步的机制对代码段进行保护,避免程序出现不确定的因素。
(二)多线程同步的实现方法
同步处理关系涉及到线程之间的通信与协作。Vb.NET中同步类提供信号处理机制,允许开发具有线程安全的代码,并实现一定程度的确定性。同步类有以下几种:①AutoResetEvent:等待句柄,用于通知一个或多个等待线程发生了一个事件。AutoResetEvent 在等待线程被释放后自动将状态更改为已发出信号;②Interlocked:为多个线程共享的变量提供原子操作;③ManualResetEvent等待句柄,用于通知一个或多个等待线程发生了一个事件;④Monitor: 提供同步访问对象的机制,调用 SyncLock 以使用监视器对象。⑤Mutex: 等待句柄,可用于进程间同步;⑥ReaderWriterLock: 定义用于实现单个写入者和多个读取者的锁定。⑦WaitHandle: 封装操作系统特有的、等待对共享资源进行独占访问的对象。
汽车售票系统案例中的遇到的问题,可用以下三种同步方法解决。
1.用Monitor类实现同步
Monitor类通过为单个线程锁定对象的方式来控制对代码块的访问,防止了其他线程访问同一代码块(临界区),当涉及到同一对象的访问时,Monitor类会阻止其它线程同时进入临界区 (代码块)。Monitor.Enter 方法指定对象上获取排他锁;Monitor.Exit 方法释放指定对象上的排他锁。Monitor类的语法规则如下:
Dim obj = New Object
Monitor.Enter(obj)
‘临界区
Monitor.Exit(obj)
在Ticket类中新增定义一个Dim obj = New Object 锁对象变量,在A点插入语句 Monitor.Enter(obj),在B点插入语句Monitor.Enter(obj)就能完成多线程的同步。
2.用SyncLock语句块实现同步
SyncLock 语句确保不会同时有多个线程执行该语句块。SyncLock 防止各个线程进入该语句块,直到没有其他线程执行它为止。它的语法规则如下:
SyncLock expression
‘'临界区
End SyncLock
其中,expression是一个表达式,它的类型必须是引用类型,如类、模块、接口、数组或委托。当线程到达SyncLock语句块时,将在指定的表达式上调用共享方法Monitor.Enter进行独占锁,这就防止了表达式在多个线程运行期间更改值,从而避免代码产生意外的结果。在Ticket类中新增一个Dim obj = New Object 锁对象变量,在A点插入语句SyncLock obj,在B点插入语句End SyncLock就能完成多线程的同步。
3.用Mutex类实现同步
Mutex是一个从WaitHandle派生的类,用于对多个复杂的线程同步的问题,它也允许单线程的访问。用来协调对要求独占访问的资源的访问,可让单个线程独占访问一项资源或者一组资源。Mutex类的WaitOne方法接受一个等待句柄作为参数,并使调用线程处于等待状态,直至另一个进程调用 Set 将当前的等待句柄设置为已发出信号。如果不使用WaitOne…ReleaseMutex语法,互斥体就不能强制访问一个对象。其语法结构如下:
Dim m_Mutex As New Mutex
m_Mutex.WaitOne()
‘临界区
m_Mutex. ReleaseMutex
在Ticket类中新增定义一个Dim m_Mutex As New Mutex互斥体变量,在A点插入语句m_Mutex.WaitOne(),
在B点插入语句m_Mutex.ReleaseMutex()就能完成多线程的同步。
三、结束语
本文就什么是线程、线程与进关系、线程的优先级、VB.NET多线程同步机制的实现方法进行了讨论。VB.NET语言的多线程还有许多问题可以研究和探讨,多线程的应用也有待于我们的进一步的挖掘。
参考文献
[1] Robertlan Oliver . Designing Enterprise Applications with Microsoft Visual Basic .net [M].Microsoft Press,2007.
[2] 岂兴明等.Visual Basic.Net 项目开发宝典[M]. 电子工业出版社,2007.
[3] 陈健.VB.NET多线程技术及其应用[J].吉林师范大学学报 2008.1.
作者简介:
包宋德男(1982-),籍贯:湖南衡阳,湖南娄底职业技术学院系统分析师,湖南大学在读软件硕士,研究方向:软件设计技术。
关键词多线程;VB.NET;同步
进程(Process)是应用程序在内存环境中基本的执行单元,进程是有不同的地址空间且处在可执行状态中的应用程序。线程(Thread)是进程中某个单一的顺序控制流程,线程不能够单独执行,它必须运行在处于活动状态的应用程序进程中,同一个进程的多个线程共享相同的内存空间,并发执行的多个线程之间存在着对临界资源的争夺问题,即互相配合的几个线程之间如何实现工作点同步的问题。
一、线程的创建
VB.NET中的多线程功能主要是通过Thread类来支持和实现的。Thread类属于.NET基础类库的System.Threading命名空间。线程自创建后就处于其生命周期中,程序可以对线程进行各种控制操作,包括启动、挂起、休眠、恢复和停止等。①创建线程Dim myThread = New System. Threading.Thread(AddressOf过程名),把一个过程定义成一个新线程以便和其他线程并发执行;②启动线程 myThread.Start 使线程从就绪状态变为运行状态;③挂起线程 myThread.suspend() 使该线程从运行变为停止状态,直到再次恢复它为止;④使线程休眠 myThread.sleep(整数值);⑤恢复线程 myThread.resume() 该线程再次启动,继续工作。⑥停止线程 myThread.abort() 该线程停止工作,并被释放,不能再被恢复。
二、线程的优先级
线程的优先级代表线程的重要程度,当有多个线程同时处于可执行状态并等待获得CPU时间,线程调度器根据各个线程的优先级来决定给谁分配CPU时间,采用“抢占式”策略来调度线程执行,优先级越高获得CPU时间的机会就越大,如果优先级相同,则遵循“先来先服务”的调度原则。VB.net使用线程的Priority属性来设置线程的优先级。常用的优级别有:AboveNormal (较高优先级)、BelowNormal(较低优先级)、Highest(最高优先级)、Lowest(最低优先级)、Normal(平均优先级)。如果要指定线程myThread的优先级为最高优先级,则用语句myThread.Priority = ThreadPriority.Highest说明。
三、多线程同步
(一)多线程需要同步的原因
由于同一进程的多个线程共享同一片存储空间,在带来的方便的同时,也会带来访问冲突等问题。比如,两个线程同时存取一个数据变量,其中一个对数据进行了修改,而另一个线程仍旧是修改前的数据,这就带来了数据不一致的问题。例如在汽车售票过程中,可能会有很多人同时购票,必须开辟多个线程同时为他们服务,假设共有60张票,分别由4个线程完成。
Class Ticket
Dim tickets As Integer = 60 ’总票数
Sub run()
While True
’A点
If tickets > 0 Then
Thread.Sleep(10) ’当前执行的线程睡眠10毫秒
Console.Write( tickets & “ ”)
tickets -= 1
End If
’B点
End While
End Sub
End Class
Private Sub Button1_Click( ~)
Dim t1, t2, t3, t4 As Thread
Dim Tticket As New Ticket
t1 = New Thread(AddressOf Tticket.run):t2 = New Thread(AddressOf Tticket.run)
t3 = New Thread(AddressOf Tticket.run):t4 = New Thread(AddressOf Tticket.run)
t1.Start() : t2.Start() : t3.Start() : t4.Start()
End Sub
单击按钮运行结果如下:60,59,…,1,0,-1,-2, 从执行结果就可以看出为什么系统中票已卖完还可以继续卖几张的原因,就是因为当系统中只有一张票的时候,第一个线程都进入了if代码段里面,买了最后一张票, tickets为0,这时时间片到了;第二个线程开始运行,买了第0张票, tickets为-1,时间片到期了。以此类推,第三、第四个线程if代码段里面,从而导致了系统继续把0,-1,-2的票打印出来,这当然不是我们想要的结果,这种结果是不正确的,这个问题的根源在于多个线程同时访问了tickets变量,单独的并发的线程访问代码段中的同一对象(tickets),则这个代码段叫做临界区,我们需要用同步的机制对代码段进行保护,避免程序出现不确定的因素。
(二)多线程同步的实现方法
同步处理关系涉及到线程之间的通信与协作。Vb.NET中同步类提供信号处理机制,允许开发具有线程安全的代码,并实现一定程度的确定性。同步类有以下几种:①AutoResetEvent:等待句柄,用于通知一个或多个等待线程发生了一个事件。AutoResetEvent 在等待线程被释放后自动将状态更改为已发出信号;②Interlocked:为多个线程共享的变量提供原子操作;③ManualResetEvent等待句柄,用于通知一个或多个等待线程发生了一个事件;④Monitor: 提供同步访问对象的机制,调用 SyncLock 以使用监视器对象。⑤Mutex: 等待句柄,可用于进程间同步;⑥ReaderWriterLock: 定义用于实现单个写入者和多个读取者的锁定。⑦WaitHandle: 封装操作系统特有的、等待对共享资源进行独占访问的对象。
汽车售票系统案例中的遇到的问题,可用以下三种同步方法解决。
1.用Monitor类实现同步
Monitor类通过为单个线程锁定对象的方式来控制对代码块的访问,防止了其他线程访问同一代码块(临界区),当涉及到同一对象的访问时,Monitor类会阻止其它线程同时进入临界区 (代码块)。Monitor.Enter 方法指定对象上获取排他锁;Monitor.Exit 方法释放指定对象上的排他锁。Monitor类的语法规则如下:
Dim obj = New Object
Monitor.Enter(obj)
‘临界区
Monitor.Exit(obj)
在Ticket类中新增定义一个Dim obj = New Object 锁对象变量,在A点插入语句 Monitor.Enter(obj),在B点插入语句Monitor.Enter(obj)就能完成多线程的同步。
2.用SyncLock语句块实现同步
SyncLock 语句确保不会同时有多个线程执行该语句块。SyncLock 防止各个线程进入该语句块,直到没有其他线程执行它为止。它的语法规则如下:
SyncLock expression
‘'临界区
End SyncLock
其中,expression是一个表达式,它的类型必须是引用类型,如类、模块、接口、数组或委托。当线程到达SyncLock语句块时,将在指定的表达式上调用共享方法Monitor.Enter进行独占锁,这就防止了表达式在多个线程运行期间更改值,从而避免代码产生意外的结果。在Ticket类中新增一个Dim obj = New Object 锁对象变量,在A点插入语句SyncLock obj,在B点插入语句End SyncLock就能完成多线程的同步。
3.用Mutex类实现同步
Mutex是一个从WaitHandle派生的类,用于对多个复杂的线程同步的问题,它也允许单线程的访问。用来协调对要求独占访问的资源的访问,可让单个线程独占访问一项资源或者一组资源。Mutex类的WaitOne方法接受一个等待句柄作为参数,并使调用线程处于等待状态,直至另一个进程调用 Set 将当前的等待句柄设置为已发出信号。如果不使用WaitOne…ReleaseMutex语法,互斥体就不能强制访问一个对象。其语法结构如下:
Dim m_Mutex As New Mutex
m_Mutex.WaitOne()
‘临界区
m_Mutex. ReleaseMutex
在Ticket类中新增定义一个Dim m_Mutex As New Mutex互斥体变量,在A点插入语句m_Mutex.WaitOne(),
在B点插入语句m_Mutex.ReleaseMutex()就能完成多线程的同步。
三、结束语
本文就什么是线程、线程与进关系、线程的优先级、VB.NET多线程同步机制的实现方法进行了讨论。VB.NET语言的多线程还有许多问题可以研究和探讨,多线程的应用也有待于我们的进一步的挖掘。
参考文献
[1] Robertlan Oliver . Designing Enterprise Applications with Microsoft Visual Basic .net [M].Microsoft Press,2007.
[2] 岂兴明等.Visual Basic.Net 项目开发宝典[M]. 电子工业出版社,2007.
[3] 陈健.VB.NET多线程技术及其应用[J].吉林师范大学学报 2008.1.
作者简介:
包宋德男(1982-),籍贯:湖南衡阳,湖南娄底职业技术学院系统分析师,湖南大学在读软件硕士,研究方向:软件设计技术。