ロック有無による処理時間の差の測定
解決したいこと
現在マルチスレッド勉強中で,ロック有無による処理時間の差を測定しています.以下の関数の処理時間を計測して,ロックなしの方がロックあり(for文内,for文外)に比べて処理時間が短くなると予想したのですが,異なる結果が出ています.特に,処理時間がロックあり(for文外)<ロックなしとなる理由が分からず困っています.この原因について,どなたかご教授願えないでしょうか?
測定結果(10回平均)
inLock(ロックあり(for文内))...約0.75秒
outLock(ロックあり(for文外))...約0.06秒
noLock(ロックなし)...約0.15秒
→処理時間について,ロックあり(for文外)<ロックなし<ロックあり(for文内)の結果となりました.
(予想はロックなし<ロックあり(for文外)<ロックあり(for文内))
該当するソースコード
// 外部の名前空間をインポート
using System;
using System.Threading;
// C#プログラムは通常1つ以上のクラスから構成される
class DataRaceExample
{
// 共有変数として使用するためstatic宣言
// 本課題では複数スレッドからのアクセスを想定
static int sharedVariable = 0;
const int number = 10000000; // 10^8
// 共有オブジェクトとして使用するためstatic宣言
// 本オブジェクトはロックのために使用
static object lockObject = new object();
// インスタンス作成
// 共有変数と操作をインスタンスで共有するためstatic宣言
static void IncrementSharedVariable_noLock()
{
// 100万回インクリメント
for (int i = 0; i < number; i++)
{
sharedVariable++;
}
}
static void IncrementSharedVariable_inLock()
{
// 100万回インクリメント
for (int i = 0; i < number; i++)
{
// lockステートメントより同時アクセスを制御
lock (lockObject)
{
sharedVariable++;
}
}
}
static void IncrementSharedVariable_outLock()
{
lock (lockObject)
{
// 100万回インクリメント
for (int i = 0; i < number; i++)
{
sharedVariable++;
}
}
}
// インスタンスを作成せずに実行させるためstatic宣言
static void Main()
{
var sw = new System.Diagnostics.Stopwatch();
// 2つのスレッドを作成
// 同じメソッドIncrementSharedVariableを実行
Thread thread1 = new Thread(IncrementSharedVariable_inLock);
Thread thread2 = new Thread(IncrementSharedVariable_inLock);
Thread thread3 = new Thread(IncrementSharedVariable_inLock);
Thread thread4 = new Thread(IncrementSharedVariable_inLock);
/*Thread thread1 = new Thread(IncrementSharedVariable_outLock);
Thread thread2 = new Thread(IncrementSharedVariable_outLock);
Thread thread3 = new Thread(IncrementSharedVariable_outLock);
Thread thread4 = new Thread(IncrementSharedVariable_outLock);*/
/*Thread thread1 = new Thread(IncrementSharedVariable_noLock);
Thread thread2 = new Thread(IncrementSharedVariable_noLock);
Thread thread3 = new Thread(IncrementSharedVariable_noLock);
Thread thread4 = new Thread(IncrementSharedVariable_noLock);*/
sw.Start();
// メソッドIncrementSharedVariableを同時に実行
thread1.Start();
thread2.Start();
thread3.Start();
thread4.Start();
// Mainメソッドの終了防止のためthread1とthread2の実行が終了するまで待機
thread1.Join();
thread2.Join();
thread3.Join();
thread4.Join();
sw.Stop();
// 最終的なsharedVariableの値を表示(予測できない値になっている)
Console.WriteLine("Final shared variable value: " + sharedVariable);
Console.WriteLine("time: " + sw.Elapsed);
// ウィンドウが閉じて値が見られなくなるのを防ぐため.文字入力まで待機
// Console.ReadKey();
}
}
自分で試したこと
ここに問題・エラーに対して試したことを記載してください。
・スレッド数の増加(4,8,16など)
・統合開発環境のコード最適化OFF