スレッドセーフのコスト

マルチスレッド対応するには同期させる必要があります。.NETではその為に、幾つかの手段を提供していますが、パフォーマンス面でどのような差があるのでしょうか?

using System;
using System.Threading;
using System.Runtime.CompilerServices;

class TheClass
{
  const int LEN = 14;
  const int LOOP = 10000000;

  public int  num;

  // ロックなし
  public void Inc() {
    ++num;
  }

  // ロックあり
  public void IncLockThis() {
    lock (this) {
      ++num;
    }
  }

  // インクリメント/デクリメント専用
  public void Incerlocked() {
    Interlocked.Increment(ref num);
  }

  // 同期メソッド
  [MethodImpl(MethodImplOptions.Synchronized)]
  public void IncMethodImpl() {
    ++num;
  }

  static void Main(string[] args)
  {
    DateTime t;
    TheClass the = new TheClass();

    t = DateTime.Now;
    for (int i = 0; i < LOOP; ++i)
      the.Inc();
    Console.WriteLine("{0} : {1}", "Inc".PadRight(LEN), DateTime.Now - t);

    t = DateTime.Now;
    for (int i = 0; i < LOOP; ++i)
      the.IncLockThis();
    Console.WriteLine("{0} : {1}", "IncLockThis".PadRight(LEN), DateTime.Now - t);

    t = DateTime.Now;
    for (int i = 0; i < LOOP; ++i)
      the.Incerlocked();
    Console.WriteLine("{0} : {1}", "Incerlocked".PadRight(LEN), DateTime.Now - t);

    t = DateTime.Now;
    for (int i = 0; i < LOOP; ++i)
      the.IncMethodImpl();
    Console.WriteLine("{0} : {1}", "IncMethodImpl".PadRight(LEN), DateTime.Now - t);
  }
}

/* 結果
Inc            : 00:00:00.1718750
IncLockThis    : 00:00:00.6562500
Incerlocked    : 00:00:00.2500000
IncMethodImpl  : 00:00:00.5468750 */

lockよりMethodImplOptions.Synchronizedの方が僅かにパフォーマンスが良いみたいです。ところで、日記上でパフォーマンスネタを良く取り上げてますが、これはネタとして扱いやすいこともありますが、それよりも.NET上でのパフォーマンスについての感覚を身につけるためだったりします。C/C++ならある程度想像がついたんですが、.NETだとまだまだ読み切れないところが多くて・・・