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 (5)

  1. Guruparan says:

    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!

  2. 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.

  3. x11mnt says:

    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.

  4. hunterb46 says:

    Actually if you use volatile instead, its even better.

  5. Markus Ewald says:

    @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.

Skip to main content