最近在工作中经常用到了多线程来处理问题,但是关于多线程共享变量的问题就需要解决了。还好.net为我们提供了InterLocked类,它可是微软专门为多个线程共享的变量提供原子操作的类。我们经常用到的方法之一是Interlocked.Increment()和Interlocked.Decrement()。
如下是MSDN上关于这2个方法的介绍:
Increment 和Decrement
方法递增或递减变量并将结果值存储在单个操作中。在大多数计算机上,增加变量操作不是一个原子操作,需要执行下列步骤:
-
将实例变量中的值加载到寄存器中。
-
增加或减少该值。
-
在实例变量中存储该值。
如果不使用
Increment 和Decrement,线程会在执行完前两个步骤后被抢先。然后由另一个线程执行所有三个步骤。当第一个线程重新开始执行时,它覆盖实例变量中的值,造成第二个线程执行增减操作的结果丢失。
关于Interlocked类的更详细介绍我们可以参考MSDN上的介绍:
http://msdn.microsoft.com/zh-cn/library/system.threading.interlocked%28v=VS.100%29.aspx。
其实我们还有另外一直方法在多线程中锁定变量或者文件等进行操作,如下所示:
lock ()
{
//do something...
}
通常,应避免锁定 public 类型,否则实例将超出代码的控制范围。常见的结构 lock (this)、lock (typeof (MyType)) 和 lock ("myLock") 违反此准则:如果实例可以被公共访问,将出现C# lock this问题。如果 MyType 可以被公共访问,将出现 lock (typeof (MyType)) 问题。由于进程中使用同一字符串的任何其他代码将共享同一个锁,所以出现 lock(“myLock”) 问题。来看看C# lock this问题:如果有一个类Class1,该类有一个方法用lock(this)来实现互斥:
- publicvoidMethod2()
- {
- lock(this)
- {
- System.Windows.Forms.MessageBox.Show("Method2End");
- }
- }
如果在同一个Class1的实例中,该Method2能够互斥的执行。但是如果是2个Class1的实例分别来执行Method2,是没有互斥效果的。因为这里的lock,只是对当前的实例对象进行了加锁。
Lock(typeof(MyType))锁定住的对象范围更为广泛,由于一个类的所有实例都只有一个类型对象(该对象是typeof的返回结果),锁定它,就锁定了该对象的所有实例,微软现在建议,不要使用lock(typeof(MyType)),因为锁定类型对象是个很缓慢的过程,并且类中的其他线程、甚至在同一个应用程序域中运行的其他程序都可以访问该类型对象,因此,它们就有可能代替您锁定类型对象,完全阻止您的执行,从而导致你自己的代码的挂起。
锁住一个字符串更为神奇,只要字符串内容相同,就能引起程序挂起。原因是在.NET中,字符串会被暂时存放,如果两个变量的字符串内容相同的话,.NET会把暂存的字符串对象分配给该变量。所以如果有两个地方都在使用lock(“my lock”)的话,它们实际锁住的是同一个对象。到此,微软给出了个lock的建议用法:锁定一个私有的static 成员变量。
.NET在一些集合类中(比如ArrayList,HashTable,Queue,Stack)已经提供了一个供lock使用的对象SyncRoot,用Reflector工具查看了SyncRoot属性的代码,在Array中,该属性只有一句话:return this,这样和lock array的当前实例是一样的。ArrayList中的SyncRoot有所不同
- get
- {
-
if(this._syncRoot==null)
- {
- Interlocked.CompareExchange(refthis._syncRoot,newobject(),null);
- }
- returnthis._syncRoot;
要特别注意的是MSDN提到:从头到尾对一个集合进行枚举本质上并不是一个线程安全的过程。即使一个集合已进行同步,其他线程仍可以修改该集合,这将导致枚举数引发异常。若要在枚举过程中保证线程安全,可以在整个枚举过程中锁定集合:
- QueuemyCollection=newQueue();
- lock(myCollection.SyncRoot){
- foreach(ObjectiteminmyCollection){
- //Insertyourcodehere.
- }
- }
分享到:
相关推荐
- `Interlocked`类:提供原子操作,如增加、减小、交换等,避免竞态条件。 5. **异步编程模型**:C#从4.0版本开始引入了异步编程模型,主要基于`async`和`await`关键字。这种方式允许主线程在等待异步操作完成时...
总的来说,`Interlocked`类在C#多线程编程中扮演着重要的角色,它提供了简单且高效的原子操作,可以避免复杂的锁机制。通过合理利用`Interlocked`类,开发者可以编写出更加高效、可靠的多线程代码。然而,尽管`...
在示例中,`Interlocked`类提供了几个原子操作方法,如`Increment`和`Decrement`。`Interlocked.Increment(ref safeInstanceCount)`会原子性地增加`safeInstanceCount`的值,而`Interlocked.Decrement(ref ...
- `Interlocked`: 提供原子操作,如`Interlocked.Increment`和`Interlocked.Decrement`,用于线程安全地增加或减少变量。 3. **线程池**: .NET框架中的`ThreadPool`提供了一种高效的线程管理方式,可以复用已...
`Interlocked`类提供原子操作,如`Increment`、`Decrement`,确保线程安全的计数。 4. **异步编程** .NET Framework 4.0引入了`Task Parallel Library (TPL)`,简化了异步编程。`Task`类代表一个异步操作,`async`...
7. **Interlocked类**:该类提供了原子操作,保证了多线程环境中的数据一致性,例如Interlocked.Increment和Interlocked.Decrement用于线程安全的计数。 8. **Thread.Join**:此方法用于等待特定线程结束。在调用...
在编程领域,多线程是实现并发执行任务的关键技术,特别是在C#这样的语言中,它提供了丰富的多线程支持。本文将深入探讨C#中的多线程实例,以帮助开发者理解如何有效地利用多核处理器资源,提高程序的执行效率。 多...
2. `Interlocked`类:在多线程环境中,当多个线程访问同一变量时,可能导致数据不一致。`Interlocked`类提供了一些原子操作,确保在并发环境下的数据一致性,例如`Increment`和`Decrement`方法。 3. `Mutex`和`...
3. 使用`Interlocked`类:提供一系列原子操作,如`Increment`、`Decrement`、`CompareExchange`等,保证多线程环境下的数据一致性。 四、线程池与异步编程 1. ThreadPool类:线程池可以高效利用系统资源,避免频繁...
在.NET框架中,C#提供了两种Timer类,用于在多线程环境中实现定时触发操作:System.Threading.Timer和System.Timers.Timer。这两种Timer虽然都与时间调度相关,但在使用上和特性上有所不同。在这个主题中,我们将...
本资源“C#多线程编程实战Code源代码”来源于华章出版社,提供了丰富的实例来帮助开发者深入理解和应用多线程。 一、C#中的线程 C#语言提供了对线程的内置支持,通过System.Threading命名空间,我们可以创建和管理...
- **Interlocked类**:提供了一组原子操作,用于在多线程环境下安全地修改变量值。 - **Task Parallel Library(TPL)**:提供了基于任务的并行编程模型,简化了多线程编程。 总之,C#作为一种现代化的编程语言,在...
3. 使用volatile或Interlocked操作来设置一个共享变量,让线程自行检测并优雅地退出。 五、Winform与多线程交互 在Winform中,直接在非UI线程中修改UI控件是不允许的,会抛出CrossThreadException异常。为了安全地...
- **Interlocked**:提供原子操作,用于更新变量,防止数据竞争。 3. **死锁**:当两个或更多线程互相等待对方释放资源而无法继续执行时,就会发生死锁。预防死锁的方法包括: - 避免循环等待:确保资源总是按...
- **Interlocked操作**:如`Interlocked.Increment()`,提供原子操作,用于更新计数器等简单操作,避免锁竞争。 4. **线程通信** - **ManualResetEvent 和 AutoResetEvent**:事件信号,用于线程间的等待和通知。...
Interlocked类提供了对共享变量执行原子操作的方法,比如增加、减少等。Semaphore类可以限制对资源的并发访问数量,而ReaderWriterLock类允许允许多个读取者同时访问资源,但写入者需要独占访问。BackgroundWorker类...
4. **Interlocked**:原子操作类,提供对单个变量的原子操作。 **五、WinForms中的多线程** 在Windows Forms应用中,UI线程负责更新界面,而后台线程执行计算任务。由于跨线程访问UI控件是不允许的,我们需要使用`...
- 创建线程:在C#中,可以通过`System.Threading.Thread`类创建新线程,或者使用`Task`类来并行执行操作。 - 线程同步:为了防止数据竞争和确保线程安全,可以使用`lock`语句、`Monitor`类、`Mutex`、`Semaphore`...