一、描述
MSDN :为多个线程共享的变量提供原子操作。通过System.Threading命名空间的Interlocked类控制计数器,从而实现线程的同步与互斥。Iterlocked类的部分方法如下表:
二、原理
当线程正在更新可被其他线程访问的变量时,或者当两个线程同时在不同的处理器上执行时。确保 此类的成员不会引发异常。
在大多数计算机上,递增变量不是原子操作,需要执行以下步骤:
-
将实例变量中的值加载到寄存器中。
-
递增或减小值。
-
将值存储在实例变量中。
如果不使用 Increment 和 Decrement,则在执行前两个步骤后,可以抢占线程。 然后,另一个线程可以执行所有三个步骤。 当第一个线程继续执行时,它将覆盖实例变量中的值,并且由第二个线程执行的增量或减量的影响将丢失。
Add 方法以原子方式将整数值添加到整数变量中,并返回变量的新值。
Exchange 方法以原子方式交换指定变量的值。
CompareExchange 方法组合了两个操作:比较两个值,并根据比较结果将第三个值存储在一个变量中。 比较和交换操作以原子操作的方式执行。
三、实例
使用Interlocked.Exchange实现线程的互斥
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace 测试interlock
{
class Program
{
//0 for false, 1 for true.
private static int usingResource = 0;
private const int numThreadIterations = 5;
/// <summary>
/// 创建线程的个数
/// </summary>
private const int numThreads = 5;
static void Main()
{
Thread myThread;
Random rnd = new Random();
for (int i = 0; i < numThreads; i++)
{
myThread = new Thread(new ThreadStart(MyThreadProc));
myThread.Name = String.Format("Thread{0}", i + 1);
Thread.Sleep(rnd.Next(0, 1000)); //Wait a random amount of time before starting next thread.
myThread.Start();
}
Console.ReadKey();
}
private static void MyThreadProc()
{
for (int i = 0; i < numThreadIterations; i++)
{
UseResource();
Thread.Sleep(1000); //Wait 1 second before next attempt.
}
}
/// <summary>
/// 一个简单方法,模拟线程竞争使用临界资源
/// </summary>
/// <returns></returns>
static bool UseResource()
{
if (0 == Interlocked.Exchange(ref usingResource, 1)) //将usingResource设为1,但返回原始值0
{
Console.WriteLine("{0} acquired the lock", Thread.CurrentThread.Name);
Thread.Sleep(500); //模拟一些操作
Console.WriteLine("{0} exiting lock", Thread.CurrentThread.Name);
Interlocked.Exchange(ref usingResource, 0); //Release the lock
return true;
}
else
{
Console.WriteLine(" {0} was denied the lock", Thread.CurrentThread.Name);
return false;
}
}
}
}
参考:
https://www.cnblogs.com/yy1234/p/11159177.html