1. ホーム
  2. c#

[解決済み] javaのsynchronizedキーワードのC#版?

2022-03-17 21:01:07

質問

c#はJavaの"synchronized"キーワードの独自のバージョンを持っていますか?

つまり、javaでは、関数、オブジェクト、コードブロックのいずれかに指定することができる、ということです。

public synchronized void doImportantStuff() {
   // dangerous code goes here.
}

または

public void doImportantStuff() {
   // trivial stuff

   synchronized(someLock) {
      // dangerous code goes here.
   }
}

解決方法は?

第一に、ほとんどのクラスはスレッドセーフである必要はありません。使用方法 YAGNI スレッドセーフを適用するのは、実際に使用する(そしてテストする)ことが分かっているときだけにしてください。

メソッドレベルのものについては [MethodImpl] :

[MethodImpl(MethodImplOptions.Synchronized)]
public void SomeMethod() {/* code */}

これは、アクセサ(プロパティやイベント)にも使用できます。

private int i;
public int SomeProperty
{
    [MethodImpl(MethodImplOptions.Synchronized)]
    get { return i; }
    [MethodImpl(MethodImplOptions.Synchronized)]
    set { i = value; }
}

なお、フィールドのようなイベント はデフォルトで同期化されていますが、自動実装のプロパティは はありません。 :

public int SomeProperty {get;set;} // not synchronized
public event EventHandler SomeEvent; // synchronized

個人的に、私は MethodImpl をロックしてしまうので this または typeof(Foo) - これはベストプラクティスに反しています。望ましいのは、独自のロックを使用することです。

private readonly object syncLock = new object();
public void SomeMethod() {
    lock(syncLock) { /* code */ }
}

フィールドライクイベントの場合、ロックの実装はコンパイラに依存することに注意してください。古い Microsoft コンパイラでは lock(this) / lock(Type) - が、しかし 最近のコンパイラでは Interlocked を更新することで、厄介な部分なしにスレッドセーフを実現しています。

これにより、よりきめ細かい使い方が可能になり Monitor.Wait / Monitor.Pulse などで、スレッド間の通信を行います。

関連する ブログエントリー (後に 再訪問 ).