ミューテックスは、C/C++ などの多くのプログラミング言語で非常に一般的です。Javaでそれらが恋しいです。ただし、自分で書く方法は複数ありますclass Mutex
。
最速 (最高の実行時間)の方法は何ですか? 同期が最も一般的だと思いますが、パフォーマンスはどうでしょうか。
ミューテックスは、C/C++ などの多くのプログラミング言語で非常に一般的です。Javaでそれらが恋しいです。ただし、自分で書く方法は複数ありますclass Mutex
。
最速 (最高の実行時間)の方法は何ですか? 同期が最も一般的だと思いますが、パフォーマンスはどうでしょうか。
ミューテックスは、C/C++ などの多くのプログラミング言語で非常に一般的です。Javaでそれらが恋しいです。
私があなたをフォローしているかどうかわかりません (特に、あなたが質問に答えているため)。
public class SomeClass {
private final Object mutex = new Object();
public void someMethodThatNeedsAMutex() {
synchronized(mutex) {
//here you hold the mutex
}
}
}
または、単純にメソッド全体を同期させることもできます。これはthis
、mutex オブジェクトとして使用するのと同じです。
public class SomeClass {
public synchronized void someMethodThatNeedsAMutex() {
//here you hold the mutex
}
}
最速 (最高の実行時間) の方法は何ですか?
モニターの取得/解放自体は、重大なパフォーマンスの問題にはなりません (影響の分析については、このブログ記事を参照してください)。しかし、多くのスレッドがロックを争うと、競合が発生し、パフォーマンスが低下します。
その場合、最善の戦略は、主にデータを読み取る場合、「ロックフリー」アルゴリズムを使用してミューテックスを使用しないことです (コメントでマルコが指摘したように、ロックフリーは CAS 操作を使用します。これには、何度も書き込みを再試行する必要がある場合があります)書き込みスレッドが多く、最終的にはパフォーマンスが低下する場合) または、スレッド間であまりにも多くのものを共有しないようにすることで、さらに良くなります。
反対の場合です。Java 設計者はそれを認識できないほどうまく解決しました。必要なのは、修飾子Mutex
だけで、ファーストクラスのオブジェクトは必要ありません。synchronized
ミューテックスを入れ子にしない方法でジャグリングしたいという特別なケースがある場合は、常にそこにあり、粗いミューテックスをはるかに超える同期ツールの宝庫を提供しますReentrantLock
。java.util.concurrent
Javaでは、各オブジェクトをMutexとして使用できます。
このオブジェクトは通常、「lock」または「mutex」という名前です。
そのロックへの外部アクセスを回避するため、優先されるバリアントであるオブジェクトを自分で作成できます。
// usually a field in the class
private Object mutex = new Object();
// later in methods
synchronized(mutex) {
// mutual exclusive section for all that uses synchronized
// ob this mutex object
}
別のスレッドが実際以外の値を読み取った場合に何が起こるかを考えることにより、ミューテックスを回避する方が高速です。状況によっては、これにより誤った計算結果が生成される場合もあれば、最小限の遅延でしか生成されない場合もあります。(ただし、同期よりも高速です)
本の詳細な説明
実際のJavaConcurreny
。
最速の(最高のランタイム)方法は何ですか?
それは多くのことに依存します。たとえば、ReentrantLock
以前は競合を使用するよりもパフォーマンスが優れていましたが、ロックをsynchronized
最適化する新しいHotSpotバージョンがリリースされたときに変更されました。synchronized
したがって、(パフォーマンスの観点から)ミューテックスの1つのフレーバーを他のフレーバーよりも優先するロックの方法に固有のものはありません。実際、「最良の」ソリューションは、処理しているデータと使用しているマシンによって変わる可能性があります。で実行しています。
また、なぜJavaの発明者は私のためにこの質問を解決しなかったのですか?
彼らは-いくつかの方法で- synchronized
、Lock
s、アトミック変数、および。の他の多くのユーティリティを実行しましたjava.util.concurrent
。
アトミック、同期、ロックなど、各バリアントのマイクロ ベンチマークを実行できます。他の人が指摘しているように、マシンと使用中のスレッドの数に大きく依存します。long 整数をインクリメントする私自身の実験では、Xeon W3520 上の 1 つのスレッドのみで、同期がアトミックに勝つことがわかりました: アトミック/同期/ロック: 8.4/6.2/21.8、インクリメント操作あたりのナノ単位。競合が発生することはないため、これはもちろん境界ケースです。もちろん、その場合、非同期のシングル スレッドのロング インクリメントを調べることもできます。これは、アトミックよりも 6 倍高速です。
4 つのスレッドを使用すると、21.8/40.2/57.3 になります。これらはすべてすべてのスレッドで増加しているため、実際には速度が低下していることに注意してください。22.2/45.1/45.9 の 64 スレッドのロックでは、少し良くなります。
Xeon E7-4820 を使用した 4-way/64T マシンでの別のテストでは、1 スレッド: 9.1/7.8/29.1、4 スレッド: 18.2/29.1/55.2、および 64 スレッド: 53.7/402/420 が得られます。
もう 1 つのデータ ポイントは、今回はデュアル Xeon X5560、1T: 6.6/5.8/17.8、4T: 29.7/81.5/121、64T: 31.2/73.4/71.6 です。
そのため、マルチソケット マシンでは、キャッシュの一貫性に大きな負担がかかります。
ミューテックスまたは java.util.concurrent.Semaphore と同じ方法で java.util.concurrent.locks.Lock を使用できます。しかし、同期キーワードを使用する方が良い方法です:-)
よろしくアンドレイ