Javaの同期キーワードのC#バージョン?


313

c#には、独自のバージョンのJavaの「synchronized」キーワードがありますか?

つまり、Javaでは、次のように、関数、オブジェクト、またはコードブロックのいずれかに指定できます。

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

または

public void doImportantStuff() {
   // trivial stuff

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

3
ブロックフォームには、ロックするための参照が必要です。メソッド形式では、ロックオブジェクトは暗黙的にthis(または静的メソッドの場合はクラス[this.class、getClass()ではない]ですが、クラスをロックしません)。
トム・ホーティン-タックライン09

1
まだ保護されていませんか?その[MethodImpl(MethodImplOptions.Synchronized)]行を思い出せないので、いつもここに来ます。
Bitterblue 2014年

1
2番目のスニペットはコンパイルできないと思います- 何かで同期する必要があります。
PoweredByRice

回答:


466

まず、ほとんどのクラスはスレッドセーフである必要はありません。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などを使用してスレッド間で通信できます。

関連するブログエントリ(後で再検討)。


@earcamとあなたの質問は?その声明は真実です。クラスの大部分は、スレッドセーフである必要がなく、スレッドセーフティについてテストされません。またスレッドセーフティがあるとパフォーマンスに影響します。スレッドについて本当に心配する必要がある型の数は非常に少ない-意図的に同期されたコレクション、マルチプレクサなど
マークグラベル

4
私は単純に述べるべきだったと思います。「ほとんどのクラスはスレッドセーフである必要はありません」が、「すべての開発者は並行性を認識している必要があります」。振り返ってみると、数が非常に少ないことに同意します(間違いなく、一度に1か所で正しく処理したいもので、クラスの大多数がマルチスレッド環境に気付かずに対話できるようにします)。コメントをより早く削除したいと思います=)
earcam

6
Marcのリンクされたブログ投稿に2010年3月のフォローアップがあり、.NET 4.0ではMethodImplフィールドのようなイベントが適切な同期コードを生成するため、独自のロックを使用する必要がなくなりました。
Rory O'Kane

2
最近のアプリケーションの大部分はWebベースであり、依存関係の注入を介した大量のインスタンスの再利用と複雑なオブジェクトのライフサイクルに依存するフレームワークで提供されています。最近のデフォルトの考え方は、スレッド・セーフティーの側面を誤る傾向があります。
Sheepy

1
@Elazarは今では遅すぎますが、参考までに:.net標準/ .netコアテンプレートを使用してフレームワークを作成した場合、フレームワークの変更はcsprojに対する1行の変更であり、通常の.netが利用可能です。 -ターゲティング。ただし、これに関連するIDEツールはひどいものです。何をどのように変更できるかを知る必要があるだけです:)
Marc Gravell

56
static object Lock = new object();

lock (Lock) 
{
// do stuff
}

10
ロックオブジェクトを静的として宣言してもよろしいですか?
serg10、2009

21
もちろん、すべてのスレッドは参照を渡さなくても簡単にアクセスできます。
Jan Gressmann、

33
質問者の質問のコンテキストにいる場合は、インスタンスメソッドについて話しています。staticを使用すると、スレッド1がinstance1.DoSomething()を呼び出し、スレッド2がinstance2.DoSomethingを呼び出す場合、2番目の呼び出しは完全に異なるオブジェクトであってもブロックされます。thread2の呼び出しは、誰かが同じオブジェクトで DoSomethingを呼び出していない限りブロックされるべきではありません。あなたが間違っていると言っているわけではありませんが、ここではstaticを使用する効果を理解することが重要です。なぜなら、インスタンスごとではなくグローバルにブロックすることによってパフォーマンスが低下する可能性があるためです。
AaronLS 2013

1
@AaronLSオブジェクトがそれ自体よりも大きなスコープでアクションを実行するときに非常に役立つ場合、静的ロック。たとえば、常にWebサービスで発生します。
Thibault D.

4
これは、OPが要求する動作とは異なるため、-1。これはクラスロックであり、インスタンスロックではありません。
tster 2013年

39

c#には、独自のバージョンのJavaの「synchronized」キーワードがありますか?

いいえ。C#では、lock非同期スレッド間で同期的に作業するリソースを明示的に指定します。lockブロックを開きます。メソッドレベルでは機能しません。

ただし、ランタイムでlock呼び出してMonitor.Enter(その後Monitor.Exit)実行するため、基本的なメカニズムは似ています。Sunのドキュメントによると、Javaは同じように機能します


3
同等の「キーワード」はありませんが、上記のMarc Gravellの回答が示すように、[MethodImpl(MethodImplOptions.Synchronized)]アノテーションを使用してメソッドレベルで同期できます。
MindJuice 2013年

1
Javaのsynchronizedonメソッドは基本的synchronized (this.getClass())にC#と似ているのではないでしょうlock(typeof(this))か?
スリハルシャチラカパティ2017

2
@SriHarshaChilakapatiこれは部分的にしか正しくありませんsynchronizedが、メソッドでのjavaのキーワードsynchronized(this)は次のようになりsynchronized(class)ます。
bvdb 2018

6

フルパスで行を書き留めてください:次の[MethodImpl(MethodImplOptions.Synchronized)]ようになります

[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.Synchronized)]


1
またはあなただけ使用することができますusing System.Runtime.CompilerServices;
codidact.comに移動aloisdg

このコメントを書いたのは、C#を数日または数週間プログラミングした後、usingステートメントを自動的に挿入することについてまだ知らなかったときでした。これら3つの賛成投票には驚いています。
Traubenfuchs 2015

1
あなたは:)少なくとも3人の開発者を助けたとの素敵なこと
codidact.comに移動aloisdg

5

lock代わりにステートメントを使用できます。これは2番目のバージョンのみを置き換えることができると思います。また、synchronizedlockはオブジェクトを操作する必要があることを忘れないでください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.