1

複数のスレッドから単純な文字列連結関数を呼び出しています。思うようにロックしました。ロックありまたはロックなしで多くのテストを行いました。それは決して失敗しませんでした。

私の質問は: 文字列連結をロックする必要がありますか?

private readonly object idLock = new object();

private string GetId(string input1, string input2, string input3)
{
    lock (idLock)
        return string.Format("{0}; {1}; {2}", input1, input2, input3);
}

PLINQ を使用して次のバリアントをテストしました - 10000000 サイクル。ミリ秒単位の時間は次のとおりです。

// Time 5446
lock (idLock)
    return string.Format("{0}; {1}; {2}", input1, input2, input3);

// Time 3728
lock (idLock)
    return input1 + "; " + input2 + "; " + input3;

// Time 953
return string.Format("{0}; {1}; {2}", input1, input2, input3);

// Time 652
return input1 + "; " + input2 + "; " + input3;

完全なテスト コードはこちら: Test Parallel String Concatenation

4

2 に答える 2

3

私の質問は: 文字列連結をロックする必要がありますか?

いいえ、ロックは必要ありません。MSDN は、System.Stringスレッド セーフであると述べています(メソッドを含むメソッドも同様Formatです)。

.Net 文字列はimmutableであるため、これは驚くべきことではありません。つまり、作成後に値を変更することはできません。不変型は本質的にスレッド セーフです。これは、あるスレッドが値にアクセスしている間は別のスレッドがその値を変更できないためです。入力パラメーターがmutableである他の参照型である場合、潜在的な問題が発生する可能性があります。

于 2013-07-06T19:02:56.947 に答える
3

いいえ、ロック構造を持つ必要はありません。

純粋なメソッドは、マルチスレッド環境で問題なく機能します。

「純粋な」とは、次のような方法を意味します。

  • この関数は、同じ引数値が与えられた場合、常に同じ結果値を評価します。関数の結果の値は、プログラムの実行が進行するにつれて、またはプログラムの異なる実行間で変化する可能性のある非表示の情報または状態に依存することはできません。また、I/O デバイスからの外部入力に依存することもできません。
  • 結果の評価は、変更可能なオブジェクトの変更や I/O デバイスへの出力など、意味的に観察可能な副作用や出力を引き起こしません。

(出典:ウィキペディア: Pure Function )

あなたの場合、文字列の連結自体はマルチスレッド環境で問題なく、ロック構造は必要ありません。

ただし、他のスレッドで変更できるフィールドまたはプロパティから読み取った文字列を連結している場合は、システムの安定性を確保するためにロックなどが必要になりますが、質問のサンプルコードはありません.

于 2013-07-06T18:41:44.317 に答える