C#でのJavaのようなスレッド同期
-
06-07-2019 - |
質問
私はJavaプログラマーであり、int型Javaのスレッド化に関するいくつかのことを知っています。
Javaでは、synchronizedキーワードを使用してメソッドをロックできます。
private int a;
private int b;
private int c;
private synchronized void changeVars()
{
a = 4;
b = 2;
c = a+b;
}
msdnで検索したところ、c#にはスレッドで遊ぶおもちゃがいくつかあることがわかりました。 monitor.Enter、monitor.Exit、lock、またはAdvanced One Mutexなど。
しかし、必要なのは1つのメソッドを同期することです。 C#でそれと同等のものは何ですか?
事前に感謝します。
解決
このようなものはおそらく:
using System.Runtime.CompilerServices;
...
private int a;
private int b;
private int c;
[MethodImpl(MethodImplOptions.Synchronized)]
private void changeVars()
{
a = 4;
b = 2;
c = a+b;
}
他のヒント
C#には直接相当するものはありませんが、これで同じことができます:
private readonly object changeVarsLockObject = new object();
private void changeVars()
{
lock(changeVarsLockObject)
{
a = 4;
b = 2;
c = a+b;
}
}
明確にする-Javaで同期されたメソッドを宣言するには、呼び出し元がメソッドが呼び出された object ( Class
オブジェクト)のモニターを保持する必要があります静的メソッドの場合)。
「メソッドをロックする」ことができると言ってそのメソッドを完全にロックしないため(同じインスタンスを別のインスタンスオブジェクトで呼び出すことができます)、そのメソッドよりも多くロックします(ターゲットオブジェクトを必要とする他のコードはありません)同期された他のメソッドや明示的な取得を含むモニターを同時に実行できます。
同期は難しい。理想的には、「いくつかのこと」以上のものを知る必要がある。テスト中にほとんど表示されない、またはデバッグに役立つデッドロックや可視性の問題を回避する場合は、それについて。ある言語での同期の不完全な理解を理解し、異なるプリミティブと異なるメモリモデルを使用して別の言語にそれを引き継ごうとすると、災害のレシピになります。
したがって、これはあなたが探していたワンライナーの答えではありませんが、エコシステム全体の知識がなくても、ワンライナーの答えは失敗する運命にあると断言します。したがって、キーワードごとにJavaエクスペリエンスを翻訳しようとするのではなく、C#での同期について優れた本/チュートリアルを読む必要があります。
これに直接相当するのは、ロック(this)を使用することです:
private void ChangeVars()
{
lock (this) {
a = 4;
b = 2;
c = a+b;
}
}
または、R。Bemroseが説明したMethodImplAttributeを実際に使用します。これは同じことです:
[MethodImpl(MethodImplOptions.Synchronized)]
private void ChangeVars()
{
a = 4;
b = 2;
c = a+b;
}
...ただし、他の誰かがそれをロックオブジェクトとして使用することを決定する可能性があるため、パブリックに表示されるオブジェクトをロックに使用することは推奨されません。
private object monitor = new object();
private void ChangeVars()
{
lock (monitor) {
a = 4;
b = 2;
c = a+b;
}
}
推奨される解決策は、メソッド本体を lock
ステートメントでラップすることです。
internal class Foo
{
private Object lockObject = new Object();
private void ChangeVars()
{
lock (this.lockObject)
{
// Manipulate the state.
}
}
}
宣言的同期も使用できますが、これには ContextBoundObject
および Synchronization
属性は同じロックオブジェクトを共有し、ロックの粒度を制限します。
internal class Foo : ContextBoundObject
{
[Synchronization]
private void ChangeVars()
{
// Manipulate the state.
}
}