Freigeben über


Stopwatch on Interlocked.Increment(ref x) vs. lock (y) { x++; }

Given 10 million iterations:

 object y = new object();
const int iterations = 10000000;

Which is faster, InterlockedIncrement:

 stopWatch = Stopwatch.StartNew();
for (int i = 0; i < iterations; i++)
{
    Interlocked.Increment(ref x);
}
stopWatch.Stop();
Console.WriteLine("Interlocked took " + stopWatch.ElapsedMilliseconds);

Or lock:

 stopWatch = Stopwatch.StartNew();
for (int i = 0; i < iterations; i++)
{
    lock (y)
    {
        x++;
    }
}
stopWatch.Stop();
Console.WriteLine("lock took " + stopWatch.ElapsedMilliseconds);

The answer surprised me:

Interlocked took 168

lock took 389

Best,

Brian

Comments

  • Anonymous
    July 24, 2009
    Nice examples...here after i will need to use this method!!Also until now i have used StopWatch at all! (i never knew about it!)Now i know .net is Ocean..long way to swim!!(earlier we used timespan to count the difference in time!) stopwatch is simple & great!
  • Anonymous
    July 24, 2009
    It's not so surprising when you learn how they are implemented.A lock involves a lot of stuff -- some extra object overhead and at least two of its own Interlocked operations.Interlocked.Increment is implemented in literally a single multi-proc-safe atomic instruction of "LOCK INC" or "LOCK XADD".  It will also be much more scalable -- try running it in parallel on four cores and the perf difference will be even greater.
  • Anonymous
    July 24, 2009
    Oh, I agree.  I just expected the performance with 0 contention to be closer because I knew lock was based, in part, on interlocked operations.
  • Anonymous
    August 21, 2009
    Actually if you use volatile instead, its even better.
  • Anonymous
    August 31, 2009
    @hunterb46: A volatile x++ is not thread-safe. x++ involves a volatile read from x, then incrementing that value and a volatile write to write it back. It may be faster, but if two threads overlap at that instruction, you'll lose one increment.