2016-10-21 18 views
0

私はクラスを持っている:ReaderWriterLockSlimと参照

public static class Message 
{ 
    private static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim(); 
    private static string theMessage; 

    public static void SetMessage(string message) 
    { 
     Locker.EnterWriteLock(); 
     theMessage = message; 
     Locker.ExitWriteLock(); 
    } 

    public static string GetMessage() 
    { 
     Locker.EnterReadLock(); 
     var msg = theMessage; // <<<===== 
     Locker.ExitReadLock(); 
     return msg; 
    } 
} 

私が正しく理解していれば、尖ったラインで、私はtheMessageへの参照を作成し、それを返しています。複数のスレッドが同じ変数にアクセスするか、間違っていますか?

代わりにstring.Copyに電話をかけて、スレッドセーフであることを確認する必要がありますか? (文字列が1である)オブジェクトベースクラスの

おかげ

答えて

2

文字列は、あなたがこの行に値そのものを値にrefernceを取得していない参照型であるため:あなたはの戻り値に影響を与えるために、他のスレッドからの変更を防止したい場合は

var msg = theMessage; 

メソッドのほとんどの参照型については、私はあなたが値をコピーし、新しいコピーされた値に別の参照を返すことをお勧めします。
しかし、文字列は不変型ですので、他のスレッドは値を変更できないため、実際には問題になりません(誰も変更できません!)。

他のスレッドが戻り値を変更しないように、文字列を深くコピーする必要はありません。

これらの質問(12)を参照すると、不変オブジェクトがスレッドセーフな理由をさらに読むことができます。

2

メンバーの割り当ては、C#の原子です。ロッキングの必要は全くありません。

あなたはそれが必要になる可能性がある二つのブロックによりtheMessage = message;以外のコードとvar msg = theMessage;を持っていた場合、しかし、単一代入を使用すると、ロックが不要で行う唯一のものですので。

+0

しかし、私はまだtheStringのコピーを作成する必要がありますか? – sooqua

+2

文字列は不変です。一度インスタンスを取得すると内部状態が変更されることはありません。 'Substring(4)'や 'Trim()'のような関数はすべて、新しい***文字列を返します。 –