obsidian/笔记文件/2.笔记/Interlocked.Decrement.md

272 lines
9.8 KiB
Markdown
Raw Permalink Normal View History

2025-03-26 00:02:56 +08:00
#unity/日常积累
## 定义
命名空间:
[System.Threading](https://learn.microsoft.com/zh-cn/dotnet/api/system.threading?view=net-8.0)
程序集:
System.Threading.dll
以原子操作的形式递减指定变量的值并存储结果。
[](https://learn.microsoft.com/zh-cn/dotnet/api/system.threading.interlocked.decrement?view=net-8.0#--)
## 重载
展开表
[Decrement(Int32)](https://learn.microsoft.com/zh-cn/dotnet/api/system.threading.interlocked.decrement?view=net-8.0#system-threading-interlocked-decrement(system-int32@))
以原子操作的形式递减指定变量的值并存储结果。
[Decrement(Int64)](https://learn.microsoft.com/zh-cn/dotnet/api/system.threading.interlocked.decrement?view=net-8.0#system-threading-interlocked-decrement(system-int64@))
以原子操作的形式递减指定变量的值并存储结果。
[Decrement(UInt32)](https://learn.microsoft.com/zh-cn/dotnet/api/system.threading.interlocked.decrement?view=net-8.0#system-threading-interlocked-decrement(system-uint32@))
以原子操作的形式递减指定变量的值并存储结果。
[Decrement(UInt64)](https://learn.microsoft.com/zh-cn/dotnet/api/system.threading.interlocked.decrement?view=net-8.0#system-threading-interlocked-decrement(system-uint64@))
以原子操作的形式递减指定变量的值并存储结果。
[](https://learn.microsoft.com/zh-cn/dotnet/api/system.threading.interlocked.decrement?view=net-8.0#system-threading-interlocked-decrement(system-int32@))
## Decrement(Int32)
以原子操作的形式递减指定变量的值并存储结果。
``` cs
public static int Decrement (ref int location);
```
#### 参数
location
[Int32](https://learn.microsoft.com/zh-cn/dotnet/api/system.int32?view=net-8.0)
其值要递减的变量。
#### 返回
[Int32](https://learn.microsoft.com/zh-cn/dotnet/api/system.int32?view=net-8.0)
递减操作完成后紧接变量的值。
#### 例外
[ArgumentNullException](https://learn.microsoft.com/zh-cn/dotnet/api/system.argumentnullexception?view=net-8.0)
`location` 的地址是一个 `null` 指针。
[NullReferenceException](https://learn.microsoft.com/zh-cn/dotnet/api/system.nullreferenceexception?view=net-8.0)
`location` 的地址是一个 `null` 指针。
### 示例
以下示例确定需要多少个介于 0 到 1,000 的随机数才能生成具有中点值的 1,000 个随机数。 为了跟踪中点值的数量,变量 `midpointCount`设置为等于 1,000并在随机数生成器每次返回中点值时递减。 由于三个线程生成随机数, [Decrement(Int32)](https://learn.microsoft.com/zh-cn/dotnet/api/system.threading.interlocked.decrement?view=net-8.0#system-threading-interlocked-decrement(system-int32@)) 因此调用 方法以确保多个线程不会同时更新 `midpointCount` 。 请注意,锁还用于保护随机数生成器,并使用 对象来确保`Main`方法不会在三个[CountdownEvent](https://learn.microsoft.com/zh-cn/dotnet/api/system.threading.countdownevent?view=net-8.0)线程之前完成执行。
``` cs
using System;
using System.Threading;
public class Example
{
const int LOWERBOUND = 0;
const int UPPERBOUND = 1001;
static Object lockObj = new Object();
static Random rnd = new Random();
static CountdownEvent cte;
static int totalCount = 0;
static int totalMidpoint = 0;
static int midpointCount = 10000;
public static void Main()
{
cte = new CountdownEvent(1);
// Start three threads.
for (int ctr = 0; ctr <= 2; ctr++) {
cte.AddCount();
Thread th = new Thread(GenerateNumbers);
th.Name = "Thread" + ctr.ToString();
th.Start();
}
cte.Signal();
cte.Wait();
Console.WriteLine();
Console.WriteLine("Total midpoint values: {0,10:N0} ({1:P3})",
totalMidpoint, totalMidpoint/((double)totalCount));
Console.WriteLine("Total number of values: {0,10:N0}",
totalCount);
}
private static void GenerateNumbers()
{
int midpoint = (UPPERBOUND - LOWERBOUND) / 2;
int value = 0;
int total = 0;
int midpt = 0;
do {
lock (lockObj) {
value = rnd.Next(LOWERBOUND, UPPERBOUND);
}
if (value == midpoint) {
Interlocked.Decrement(ref midpointCount);
midpt++;
}
total++;
} while (Volatile.Read(ref midpointCount) > 0);
Interlocked.Add(ref totalCount, total);
Interlocked.Add(ref totalMidpoint, midpt);
string s = String.Format("Thread {0}:\n", Thread.CurrentThread.Name) +
String.Format(" Random Numbers: {0:N0}\n", total) +
String.Format(" Midpoint values: {0:N0} ({1:P3})", midpt,
((double) midpt)/total);
Console.WriteLine(s);
cte.Signal();
}
}
// The example displays output like the following:
// Thread Thread2:
// Random Numbers: 3,204,021
// Midpoint values: 3,156 (0.099 %)
// Thread Thread0:
// Random Numbers: 4,073,592
// Midpoint values: 4,015 (0.099 %)
// Thread Thread1:
// Random Numbers: 2,828,192
// Midpoint values: 2,829 (0.100 %)
//
// Total midpoint values: 10,000 (0.099 %)
// Total number of values: 10,105,805
```
下面的示例与上一个示例类似,只不过它使用 [Task](https://learn.microsoft.com/zh-cn/dotnet/api/system.threading.tasks.task?view=net-8.0) 类而不是线程过程来生成 50,000 个随机中点整数。 在此示例中lambda 表达式替换了 `GenerateNumbers` 线程过程,对 方法的调用 [Task.WaitAll](https://learn.microsoft.com/zh-cn/dotnet/api/system.threading.tasks.task.waitall?view=net-8.0) 消除了对 [CountdownEvent](https://learn.microsoft.com/zh-cn/dotnet/api/system.threading.countdownevent?view=net-8.0) 对象的需要。
``` cs
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
public class Example
{
const int LOWERBOUND = 0;
const int UPPERBOUND = 1001;
static Object lockObj = new Object();
static Random rnd = new Random();
static int totalCount = 0;
static int totalMidpoint = 0;
static int midpointCount = 50000;
public static async Task Main()
{
List<Task> tasks = new List<Task>();
// Start three tasks.
for (int ctr = 0; ctr <= 2; ctr++)
tasks.Add(Task.Run( () => { int midpoint = (UPPERBOUND - LOWERBOUND) / 2;
int value = 0;
int total = 0;
int midpt = 0;
do {
lock (lockObj) {
value = rnd.Next(LOWERBOUND, UPPERBOUND);
}
if (value == midpoint) {
Interlocked.Decrement(ref midpointCount);
midpt++;
}
total++;
} while (Volatile.Read(ref midpointCount) > 0);
Interlocked.Add(ref totalCount, total);
Interlocked.Add(ref totalMidpoint, midpt);
string s = String.Format("Task {0}:\n", Task.CurrentId) +
String.Format(" Random Numbers: {0:N0}\n", total) +
String.Format(" Midpoint values: {0:N0} ({1:P3})", midpt,
((double) midpt)/total);
Console.WriteLine(s);
} ));
await Task.WhenAll(tasks.ToArray());
Console.WriteLine();
Console.WriteLine("Total midpoint values: {0,10:N0} ({1:P3})",
totalMidpoint, totalMidpoint/((double)totalCount));
Console.WriteLine("Total number of values: {0,10:N0}",
totalCount);
}
}
// The example displays output like the following:
// Task 1:
// Random Numbers: 24,530,624
// Midpoint values: 24,675 (0.101 %)
// Task 2:
// Random Numbers: 7,079,718
// Midpoint values: 7,093 (0.100 %)
// Task 3:
// Random Numbers: 18,284,617
// Midpoint values: 18,232 (0.100 %)
//
// Total midpoint values: 50,000 (0.100 %)
// Total number of values: 49,894,959
```
### 注解
此方法通过包装处理溢出条件:如果 `location` = [Int32.MinValue](https://learn.microsoft.com/zh-cn/dotnet/api/system.int32.minvalue?view=net-8.0#system-int32-minvalue) `location` 则 - 1 = 。 [Int32.MaxValue](https://learn.microsoft.com/zh-cn/dotnet/api/system.int32.maxvalue?view=net-8.0#system-int32-maxvalue) 不会引发异常。
### 另请参阅
- [托管线程](https://learn.microsoft.com/zh-cn/dotnet/standard/threading/)
- [同步基元概述](https://learn.microsoft.com/zh-cn/dotnet/standard/threading/overview-of-synchronization-primitives)
### 适用于
.NET 8 和其他版本
产品
版本
.NET
Core 1.0, Core 1.1, Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8 
.NET Framework
1.1, 2.0, 3.0, 3.5, 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1 
.NET Standard
1.0, 1.1, 1.2, 1.3, 1.4, 1.6, 2.0, 2.1 
UWP
10.0 
Xamarin.iOS
10.8 
Xamarin.Mac
3.0 
[](https://learn.microsoft.com/zh-cn/dotnet/api/system.threading.interlocked.decrement?view=net-8.0#system-threading-interlocked-decrement(system-int64@))