staticを宣言したメソッドであっても、メソッド内で宣言されている変数はマルチスレッド間で共有されず、クラスのstaticメンバ変数は共有される。
staticメソッド内で宣言されている変数がマルチスレッド間で共有されないのは、変数のスコープ仕様的に、whileループの中で宣言された変数が、その外側では使えないのと同じ。
この事から、スタックメモリで実行されるstaticメソッドを、マルチスレッドアプリケーションで利用しても、安全だと分かる。
以下、実験したソースと実行結果。
実験に使用したVisual Studio 2013のプロジェクトファイル => Src2をダウンロード
メソッド内の変数を使ってループするstaticメソッドと、クラスのstaticメンバ変数を使ってループするstaticメソッド。これをシングルスレッド、マルチスレッドそれぞれで検証する。
// staticメソッド群を、マルチスレッドで実行するためのメソッド群
public class CVariable実験1
{
// メソッド内の変数を使ってループするメソッド
public void VariableTest1(object id)
{
CVariable実験2.VariableTest1(id);
}
// クラスのメンバ変数を使ってループするメソッド
public void VariableTest2(object id)
{
CVariable実験2.VariableTest2(id);
}
}
// staticメソッド群
public static class CVariable実験2
{
private static long mCnt = 0;
// メソッド内の変数を使ってループするメソッド
public static void VariableTest1(object id)
{
string FileName = "result_" + id + ".txt";
if (File.Exists(FileName)) File.Delete(FileName);
long iCnt = 0;
string tmp = null;
while (iCnt < 1000)
{
tmp = id + " " + iCnt.ToString() + "\r\n";
System.Diagnostics.Debug.WriteLine(tmp);
File.AppendAllText(FileName, tmp);
iCnt++;
}
}
// クラスのメンバ変数を使ってループするメソッド
public static void VariableTest2(object id)
{
string FileName = "result_" + id + ".txt";
if (File.Exists(FileName)) File.Delete(FileName);
string tmp = null;
mCnt = 0;
while (mCnt < 1000)
{
tmp = id + " " + mCnt.ToString() + "\r\n";
System.Diagnostics.Debug.WriteLine(tmp);
File.AppendAllText(FileName, tmp);
mCnt++;
}
}
}
1、メソッド内の変数でループするstaticメソッドを、シングルスレッドで実行する。
private void 実証実験1()
{
var Variable実験 = new CVariable実験1();
Variable実験.VariableTest1("A");
Variable実験.VariableTest1("B");
Variable実験.VariableTest1("C");
}
実行結果は、result_A.txt、result_B.txt、result_C.txtの3ファイルに、1~999がそれぞれ出力される。
2、メソッド内の変数でループするstaticメソッドを、マルチスレッドで実行する。
private void 実証実験2()
{
var Variable実験 = new CVariable実験1();
var i1 = new Thread(new ParameterizedThreadStart(Variable実験.VariableTest1));
var t2 = new Thread(new ParameterizedThreadStart(Variable実験.VariableTest1));
var t3 = new Thread(new ParameterizedThreadStart(Variable実験.VariableTest1));
i1.Start("A");
t2.Start("B");
t3.Start("C");
}
実行結果は、result_A.txt、result_B.txt、result_C.txtの3ファイルに、1~999がそれぞれ出力される。 staticメソッド内で宣言されている変数は、マルチスレッド間で共有されない。
3、クラスのstaticメンバ変数でループするstaticメソッドを、シングルスレッドで実行する。
private void 実証実験3()
{
var Variable実験 = new CVariable実験1();
Variable実験.VariableTest2("A");
Variable実験.VariableTest2("B");
Variable実験.VariableTest2("C");
}
実行結果は、result_A.txt、result_B.txt、result_C.txtの3ファイルに、1~999がそれぞれ出力される。
4、クラスのstaticメンバ変数でループするstaticメソッドを、マルチスレッドで実行する。
private void 実証実験4()
{
var Variable実験 = new CVariable実験1();
var i1 = new Thread(new ParameterizedThreadStart(Variable実験.VariableTest2));
var t2 = new Thread(new ParameterizedThreadStart(Variable実験.VariableTest2));
var t3 = new Thread(new ParameterizedThreadStart(Variable実験.VariableTest2));
i1.Start("A");
t2.Start("B");
t3.Start("C");
}
実行結果は、result_A.txt、result_B.txt、result_C.txtの3ファイルに、1~999までの値がランダムに、1ファイル辺り330行程度出力される。 クラスのstaticメンバ変数は、マルチスレッド間で共有される。
インスタンスを分けても、クラスのstaticメンバ変数は、マルチスレッド間で共有される。
最近のコメント