出于好奇,我编写了一个程序来测试InterLocked与.Net锁的性能。事实证明,InterLocked版本比锁定版本慢得多,请有人指出如果我在这里遗漏了一些细节。根据我的理解,互锁应该比锁好得多。
public class TestB
{
private static readonly object _objLocker = new object();
private long _shared;
public void IncrLocked()
{
lock (_objLocker)
{
_shared++;
}
}
public void IncrInterLocked()
{
Interlocked.Increment(ref _shared);
}
public long GetValue()
{
return _shared;
}
}
class TestsCopy
{
private static TestB _testB = new TestB();
static void Main(string[] args)
{
int numofthreads = 100;
TestInterLocked(numofthreads);
TestLocked(numofthreads);
Console.ReadLine();
}
private static void TestInterLocked(int numofthreads)
{
Thread[] threads = new Thread[numofthreads];
for (int i = 0; i < numofthreads; i++)
{
Thread t = new Thread(StartTestInterLocked);
threads[i] = t;
t.Start();
}
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < threads.Length; i++)
{
threads[i].Join();
}
sw.Stop();
Console.WriteLine($"Interlocked finished in : {sw.ElapsedMilliseconds}, value = {_testB.GetValue()}");
}
private static void TestLocked(int numofthreads)
{
Thread[] threads = new Thread[numofthreads];
for (int i = 0; i < numofthreads; i++)
{
Thread t = new Thread(StartTestLocked);
threads[i] = t;
t.Start();
}
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < threads.Length; i++)
{
threads[i].Join();
}
sw.Stop();
Console.WriteLine($"Locked finished in : {sw.ElapsedMilliseconds}, value = {_testB.GetValue()}");
}
private static void StartTestInterLocked()
{
int counter = 10000000;
for (int i = 0; i < counter; i++)
{
_testB.IncrInterLocked();
}
}
private static void StartTestLocked()
{
int counter = 10000000;
for (int i = 0; i < counter; i++)
{
_testB.IncrLocked();
}
}程序的输出是..。
Interlocked finished in : 76909 ms, value = 1000000000
Locked finished in : 44215 ms, value = 2000000000发布于 2016-05-10 08:05:38
由于Jakob提到的原因,您的测试是有缺陷的。此外,您的测试还包括在类中调用方法的开销(对于lock,显然这是调用Interlocked.Increment()时无法避免的)。
您应该启动所有线程,并安排它们在启动秒表后开始工作。您可以通过让他们在ManualResetEvent上等待来做到这一点。
我重写了您的测试代码如下:
using System;
using System.Diagnostics;
using System.Threading;
namespace Demo
{
static class Program
{
private static readonly object _objLocker = new object();
private static long _shared;
private static ManualResetEvent _signal = new ManualResetEvent(false);
static void Main(string[] args)
{
int numofthreads = 100;
TestInterLocked(numofthreads);
TestLocked(numofthreads);
Console.ReadLine();
}
private static void TestInterLocked(int numofthreads)
{
Thread[] threads = new Thread[numofthreads];
for (int i = 0; i < numofthreads; i++)
{
Thread t = new Thread(StartTestInterLocked);
threads[i] = t;
t.Start();
}
Thread.Sleep(5000); // Make sure threads have had time to start.
Stopwatch sw = new Stopwatch();
sw.Start();
_shared = 0;
_signal.Set();
for (int i = 0; i < threads.Length; i++)
{
threads[i].Join();
}
sw.Stop();
_signal.Reset();
Console.WriteLine($"Interlocked finished in : {sw.ElapsedMilliseconds}, value = {_shared}");
}
private static void TestLocked(int numofthreads)
{
Thread[] threads = new Thread[numofthreads];
for (int i = 0; i < numofthreads; i++)
{
Thread t = new Thread(StartTestLocked);
threads[i] = t;
t.Start();
}
Thread.Sleep(5000); // Make sure threads have had time to start.
Stopwatch sw = new Stopwatch();
sw.Start();
_shared = 0;
_signal.Set();
for (int i = 0; i < threads.Length; i++)
{
threads[i].Join();
}
sw.Stop();
_signal.Reset();
Console.WriteLine($"Locked finished in : {sw.ElapsedMilliseconds}, value = {_shared}");
}
private static void StartTestInterLocked()
{
_signal.WaitOne();
int counter = 10000000;
for (int i = 0; i < counter; i++)
{
Interlocked.Increment(ref _shared);
}
}
private static void StartTestLocked()
{
_signal.WaitOne();
int counter = 10000000;
for (int i = 0; i < counter; i++)
{
lock (_objLocker)
{
_shared++;
}
}
}
}
}现在的结果是(来自发行版构建):
Interlocked finished in : 11339, value = 1000000000
Locked finished in : 30546, value = 1000000000如您所见,Interlocked的速度要快得多。
https://stackoverflow.com/questions/37132209
复制相似问题