当多个线程可以调用单个对象的属性和方法时,对这些调用进行同步处理是非常重要的。否则,一个线程可能会中断另一个线程正在执行的任务,使该对象处于一种无效状态。其成员不受这类中断影响的类叫做线程安全类。
Common Language Infrastructure 提供了几种可用来同步对实例和静态成员的访问的策略:
公共语言运行时提供一个线程模型,在该模型中,类分为许多类别,这些类别可以根据要求以各种不同的方式进行同步。下表显示了为具有给定同步类别的字段和方法提供的同步支持。
类别
全局字段
静态字段
静态方法
实例字段
实例方法
特定代码块
无同步
|
否
|
否
|
否
|
否
|
否
|
否
|
同步上下文
|
否
|
否
|
否
|
是
|
是
|
否
|
同步代码区域
|
否
|
否
|
仅当标记时
|
否
|
仅当标记时
|
仅当标记时
|
手动同步
|
手动
|
手动
|
手动
|
手动
|
手动
|
手动
|
这对于对象是默认情况。任何线程都可以随时访问任何方法或字段。一次只能有一个线程访问这些对象。
.NET Framework 类库提供大量用于同步线程的类。请参见 同步基元概述。
可以使用 Monitor 类或编译器关键字来同步代码块、实例方法和静态方法。不支持同步静态字段。
Visual Basic 和 C# 都支持使用特定语言关键字标记代码块,在 C# 中使用的是 lock 语句,在 Visual Basic 中使用的是 SyncLock 语句。当由线程执行该代码时,会尝试获取锁。如果该锁已由其他线程获取,则在锁变为可用状态之前,该线程一直处于禁止状态。当线程退出同步代码块时,锁就会被释放,它与线程的退出方式无关。
还可以用 MethodImplAttribute 和 MethodImplOptions.Synchronized 修饰方法,其效果和使用 Monitor 或其中一个编译器关键字锁定整个方法体相同。
Thread::Interrupt 可用于使线程跳出阻止操作(如等待访问同步代码区域)。Thread.Interrupt 还用于使线程跳出 Thread::Sleep 等操作。
重要事项
为保护 static 方法(Visual Basic 中的 Shared 方法),请不要锁定类型,即:C# 中的 typeof(MyType)、Visual Basic 中的 GetType(MyType) 或 C++ 中的 MyType::typeid。而应改用私有静态对象。类似地,不要使用 C# 中的 this(Visual Basic 中的 Me)锁定实例方法。而应使用私有对象。类或实例可由其他代码锁定,您自己的代码进行锁定可能会引起死锁或性能问题。
|
编译器支持
Visual Basic 和 C# 都支持使用 Monitor::Enter 和 Monitor::Exit 来锁定对象的语言关键字。Visual Basic 支持 SyncLock 语句;C# 支持 lock 语句。
这两种情况下,如果代码块中引发异常,则 lock 或 SyncLock 锁获取的锁将自动释放。C# 和 Visual Basic 编译器在发出 try/finally 块时,在 try 的起始处使用 Monitor.Enter,在 finally 块中使用 Monitor.Exit。如果 lock 或 SyncLock 块内部引发了异常,则会运行 finally 处理程序,从而使您可以执行任何清除工作。
可以使用任何 ContextBoundObject 的 SynchronizationAttribute 来同步所有实例方法和字段。同一上下文域中的所有对象都共享同一个锁。允许多个线程访问方法和字段,但在任一时刻只允许一个线程访问。
分享到:
相关推荐
线程池管理线程demo,可以参考下。比较详细。将线程任务托管给线程池,减少开销。
用C#托管代码实现的线程池 它在管理线程的时候,有一个缓存线程的池,即一个ArrayList对象 它一开始就初始化了一定数量的线程,并通过ProcessQueuedItems方法保证异步执行进入池中的队列任务 这样在分配异步任务的...
线程是进程中可独立调度执行的子任务,一个进程可以有一个或多个线程,它们共享所属进程所拥有的...ThreadPool(线程池)是一个静态类,它没有定义任何的构造方法(),这是因为ThreadPool是托管线程池,是由CLR管理的。
如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙。如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间后创建另一个辅助...
由于CLR维护了托管线程池,使用过的线程并不会立即销毁,在需要的时候会继续复用。在类似ASP.NET PerCall或WCF PerCall条件下,当Call1在线程ManagedThreadId1中处理完毕后,Call2发生,而Call2很有可能也在线程...
多种类型的线程池,线程交于线程池托管,保障资源的合理利用。
4、托管线程池中的线程都是后台线程,使用new Thread方式创建的线程默认都是前台线程。 下面做个小例子来证实一下,代码如下很简单: class Program { static AutoResetEvent autoEvent =new Auto
如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙。如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间后创建另一个辅助...
如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙.如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间后创建另一个辅助线程但...
适用于托管IOCP的无锁对象池,无锁队列和线程池。
* 受托管的线程与 Windows线程 * 前台线程与后台线程 * 名为BeginXXX和EndXXX的方法是做什么用的 * 异步和多线程有什么关联 WinForm多线程编程篇 * 我的多线程WinForm程序老是抛出InvalidOperationException...
• 受托管的线程与 Windows线程 • 前台线程与后台线程 • 名为BeginXXX和EndXXX的方法是做什么用的 • 异步和多线程有什么关联 WinForm多线程编程篇 • 我的多线程WinForm程序老是抛出...
• 受托管的线程与 Windows线程 • 前台线程与后台线程 • 名为BeginXXX和EndXXX的方法是做什么用的 • 异步和多线程有什么关联 WinForm多线程编程篇 • 我的多线程WinForm程序老是抛出...
1.线程池 (Thread Pool): 线程池是用于执行异步任务的托管线程集合。当你想执行许多类似的异步任务时,使用线程池可以有效地管理资源。 2.创建新线程 (Manual Thread): 你可以使用 Thread 类来创建并管理一个新线程...
1.【代码级动诊断】接偶发性超时,调链只能看到超时接名称,看不到内部法,法 2.【池化监控】微服务/数据库线程池经常被打满,导致服务超时,排查起来常困难,如何解
C#网络应用编程第三版(人民邮电出版社)课后上机练习实验 实验二 多任务网段扫描 关键技术是将任务托管给线程池。代码在数据验证部分写得比较麻烦(本来是想拿数据绑定写的,后来放弃了),主要实现功能部分异常...
· 使用线程池、任务、取消、计时器和异步I/O操作来设计响应性强、稳定性高和伸缩性大的解决方案 · 借助于异常处理来进行状态管理 · 使用CLR寄宿、AppDomain、程序集加载、反射和C#的dynamic类型来构造具有动态...
有四种不同类型的作业: 作业在应用程序启动时运行以进行初始设置(也可以通过dropwizard中的托管实例来完成) 在关闭应用程序之前,作业在应用程序停止时运行(也可以通过dropwizard中的托管实例来完成) 在一定...
· 使用线程池、任务、取消、计时器和异步I/O操作来设计响应性强、稳定性高和伸缩性大的解决方案 · 借助于异常处理来进行状态管理 · 使用CLR寄宿、AppDomain、程序集加载、反射和C#的dynamic类型来构造具有动态...
· 使用线程池、任务、取消、计时器和异步I/O操作来设计响应性强、稳定性高和伸缩性大的解决方案 · 借助于异常处理来进行状态管理 · 使用CLR寄宿、AppDomain、程序集加载、反射和C#的dynamic类型来构造具有动态...