3

セッターがロックで保護されているが、ゲッターの周りにロックがないプロパティがあるとします。

private long _myField;
public long MyProperty
{
    get { return _myField; }
    set { lock(whatever) _myField = value; }
}

書き込みの同期(読み取りではない)に加えて、ロック、つまりMonitor.Exitにより、不安定な書き込みが発生するはずです。ここで、2つのスレッドAとBがあり、次のシーケンスが発生するとします。

  1. Aはの現在の値を読み取りますMyProperty
  2. Bはに新しい値を書き込みますMyProperty
  3. MyPropertyAはの現在の値を再度読み取ります。

Q:Aは新しい値を確認できるようになりましたか?または、私たちのロックは、Bがタイムリーにメインメモリに書き込むことを保証しましたが、他のスレッドが新しい値を読み取ることは保証しませんでしたか?または、答えは、.Net 2+で実行しているか、「より弱い」ECMA実装で実行しているかによっても異なりますか?

4

2 に答える 2

3

いいえ、読み取りには明示的なメモリバリアがないため、新しい値を確認することは「保証」されていません。

aを使用しReaderWriterLockSlimて、a)書き込みが相互にロックし、b)読み取りが常に新しい値を取得するようにすることができます。

private readonly ReaderWriterLockSlim _myFieldLock = new ReaderWriterLockSlim();
private long _myField;
public long MyProperty
{
    get 
    {
        _myFieldLock.EnterReadLock();
        try
        {
            return _myField;
        }
        finally
        {
            _myFieldLock.ExitReadLock();
        }
    }
    set
    {
        _myFieldLock.EnterWriteLock();
        try
        {
            _myField = value;
        }
        finally
        {
            _myFieldLock.ExitWriteLock();
        }
    }
}
于 2011-03-06T05:45:22.047 に答える
1

Interlocked.Readを使用した場合は、常に新しい値を読み取る必要があります。メモリフェンスの詳細については、C#でのスレッド化を参照してください。

于 2011-03-06T05:55:09.340 に答える