#unity/日常积累
定义
命名空间:
System.Threading
程序集:
System.Threading.dll
以原子操作的形式递减指定变量的值并存储结果。
重载
展开表
Decrement(Int32)
以原子操作的形式递减指定变量的值并存储结果。
Decrement(Int64)
以原子操作的形式递减指定变量的值并存储结果。
Decrement(UInt32)
以原子操作的形式递减指定变量的值并存储结果。
Decrement(UInt64)
以原子操作的形式递减指定变量的值并存储结果。
Decrement(Int32)
以原子操作的形式递减指定变量的值并存储结果。
1
|
public static int Decrement (ref int location);
|
参数
location
Int32
其值要递减的变量。
返回
Int32
递减操作完成后紧接变量的值。
例外
ArgumentNullException
location
的地址是一个 null
指针。
NullReferenceException
location
的地址是一个 null
指针。
示例
以下示例确定需要多少个介于 0 到 1,000 的随机数才能生成具有中点值的 1,000 个随机数。 为了跟踪中点值的数量,变量 midpointCount
设置为等于 1,000,并在随机数生成器每次返回中点值时递减。 由于三个线程生成随机数, Decrement(Int32) 因此调用 方法以确保多个线程不会同时更新 midpointCount
。 请注意,锁还用于保护随机数生成器,并使用 对象来确保Main
方法不会在三个CountdownEvent线程之前完成执行。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
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 类而不是线程过程来生成 50,000 个随机中点整数。 在此示例中,lambda 表达式替换了 GenerateNumbers
线程过程,对 方法的调用 Task.WaitAll 消除了对 CountdownEvent 对象的需要。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
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, location
则 - 1 = 。 Int32.MaxValue 不会引发异常。
另请参阅
适用于
.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