#unity/日常积累 # Interlocked 类 - 参考 [](https://learn.microsoft.com/zh-cn/dotnet/api/system.threading.interlocked?view=net-6.0#definition) ## 定义 命名空间: [System.Threading](https://learn.microsoft.com/zh-cn/dotnet/api/system.threading?view=net-6.0) 程序集: System.Threading.dll 为多个线程共享的变量提供原子操作。 ``` cs public static class Interlocked ``` 继承 [Object](https://learn.microsoft.com/zh-cn/dotnet/api/system.object?view=net-6.0) Interlocked [](https://learn.microsoft.com/zh-cn/dotnet/api/system.threading.interlocked?view=net-6.0#examples) ## 示例 下面的代码示例演示线程安全资源锁定机制。 ``` cs using System; using System.Threading; namespace InterlockedExchange_Example { class MyInterlockedExchangeExampleClass { //0 for false, 1 for true. private static int usingResource = 0; private const int numThreadIterations = 5; private const int numThreads = 10; 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); //Wait a random amount of time before starting next thread. Thread.Sleep(rnd.Next(0, 1000)); myThread.Start(); } } private static void MyThreadProc() { for(int i = 0; i < numThreadIterations; i++) { UseResource(); //Wait 1 second before next attempt. Thread.Sleep(1000); } } //A simple method that denies reentrancy. static bool UseResource() { //0 indicates that the method is not in use. if(0 == Interlocked.Exchange(ref usingResource, 1)) { Console.WriteLine("{0} acquired the lock", Thread.CurrentThread.Name); //Code to access a resource that is not thread safe would go here. //Simulate some work Thread.Sleep(500); Console.WriteLine("{0} exiting lock", Thread.CurrentThread.Name); //Release the lock Interlocked.Exchange(ref usingResource, 0); return true; } else { Console.WriteLine(" {0} was denied the lock", Thread.CurrentThread.Name); return false; } } } } ``` ## 注解 此类的方法有助于防止当计划程序切换上下文时,当线程更新可由其他线程访问的变量时,或者当两个线程同时在单独的处理器上执行时,可能会出现的错误。 此类的成员不会引发异常。 [Decrement](https://learn.microsoft.com/zh-cn/dotnet/api/system.threading.interlocked.decrement?view=net-6.0)和[Increment](https://learn.microsoft.com/zh-cn/dotnet/api/system.threading.interlocked.increment?view=net-6.0)方法递增或递减变量,并将结果值存储在单个操作中。 在大多数计算机上,递增变量不是原子操作,需要以下步骤: 1. 将实例变量的值加载到寄存器中。 2. 递增或递减值。 3. 将值存储在实例变量中。 如果不使用 [Increment](https://learn.microsoft.com/zh-cn/dotnet/api/system.threading.interlocked.increment?view=net-6.0) 并且 [Decrement](https://learn.microsoft.com/zh-cn/dotnet/api/system.threading.interlocked.decrement?view=net-6.0)执行前两个步骤后,可以抢占线程。 然后,另一个线程可以执行所有三个步骤。 当第一个线程恢复执行时,它会覆盖实例变量中的值,并丢失第二个线程执行的递增或递减的效果。 该方法 [Add](https://learn.microsoft.com/zh-cn/dotnet/api/system.threading.interlocked.add?view=net-6.0) 以原子方式将整数值添加到整数变量,并返回该变量的新值。 该方法 [Exchange](https://learn.microsoft.com/zh-cn/dotnet/api/system.threading.interlocked.exchange?view=net-6.0) 以原子方式交换指定变量的值。 该方法 [CompareExchange](https://learn.microsoft.com/zh-cn/dotnet/api/system.threading.interlocked.compareexchange?view=net-6.0) 结合两个操作:根据比较的结果,比较两个值,并将第三个值存储在其中一个变量中。 比较和交换操作作为原子操作执行。 确保对共享变量的任何写入或读取访问权限都是原子的。 否则,数据可能会损坏,或者加载的值可能不正确。