在进行多线程编程的时候特别重要的一点就是多线程的同步,什么是同步呢?字面意思就是使多个不在同一线程执行的代码统一到一个线程中执行,但是对执行中的线程过程却无法控制,这就造成了多个线程可能同时操作同一个变量,于是就出现了得到的结果不是想要的结果,为了避免这个情况,我们常用的方法是加锁例如locked,但是为了一个很简单的操作例如a++这样的操作频繁的locked对性能的影响得不偿失,所以就需要用到InterLocked这样的原子操作,因为原子操作是基于硬件层面的非阻塞的操作,所以性能非常的好。
下面是一个多线程的实例代码,当注释掉locked这一行的时候,可以发现几乎每一次得到的结果都不一样。
int total = 0;
object obj = new object();
for (int i = 0; i <= 50; i++)
{
Thread thread = new Thread(new ThreadStart(() =>
{
for (int j = 0; j < 20; j++)
{
lock (obj)
{
total += j;
}
}
}));
thread.Start();
}
Thread.Sleep(1000);
Console.WriteLine(total);
这段代码可以修改为如下的代码
for (int j = 0; j < 20; j++)
{
//lock (obj)
//{
// total += j;
//}
Interlocked.Add(ref total, j);
}
运行后可以看到每一次的结果都是相同的,而且都是正确的
微软为我们提供了Interlocked,他其中包含了一下方法,根据方法名就可以知道每一个方法的作用,例如上面示例的Add方法,就是将两个数字相加,而Increment和Decrement就是实现类似于x++,x—的功能。
- Add方法
作用为将location1与value相加,结果存入location1中,返回求和后的结果
int a = 10, b = 12;
int result = 0;
result = Interlocked.Add(ref a, b);
Console.WriteLine(result);
Console.WriteLine(a);
- Increment与Decrement
int a = 10, b = 12;
int result = 0;
//result = Interlocked.Add(ref a, b);
result = Interlocked.Increment(ref a);
Console.WriteLine(result);
result = Interlocked.Decrement(ref b);
Console.WriteLine(a);
Console.WriteLine(result);
Console.WriteLine(b);
- Exchange
将参数2赋值给参数1,并返回参数1的原始值
int a = 10, b = 12; int result = 0;
result = Interlocked.Exchange(ref a, b);
Console.WriteLine(result);
Console.WriteLine(a);
- CompareExchange
比较参数3与参数1如果相等则使用参数2替换参数1,返回参数1的原始值
int a = 10, b = 12, c = 12;
int result = 0;
result = Interlocked.CompareExchange(ref a, b, c);
Console.WriteLine(result);
Console.WriteLine(a);
int a = 10, b = 12, c = 10;
int result = 0;
result = Interlocked.CompareExchange(ref a, b, c);
Console.WriteLine(result);
Console.WriteLine(a);