Javaの同期メソッドと同期ブロックの違いは何ですか?
私はネットで答えを探していました、人々はこれについてとても確信が持てないようです:-(
私の考えでは、同期ブロックがスコープ内でよりローカライズされている可能性があり、したがってロックの時間が短くなることを除いて、2つの間に違いはありませんか?
そして、静的メソッドのロックの場合、ロックは何で行われますか?ロックオンクラスの意味は何ですか?
Javaの同期メソッドと同期ブロックの違いは何ですか?
私はネットで答えを探していました、人々はこれについてとても確信が持てないようです:-(
私の考えでは、同期ブロックがスコープ内でよりローカライズされている可能性があり、したがってロックの時間が短くなることを除いて、2つの間に違いはありませんか?
そして、静的メソッドのロックの場合、ロックは何で行われますか?ロックオンクラスの意味は何ですか?
同期されたメソッドは、メソッドレシーバーをロックとして使用します(つまりthis
、非静的メソッドの場合、および静的メソッドの場合はそれを囲むクラス)。 Synchronized
ブロックは式をロックとして使用します。
したがって、次の2つの方法は、プロスペクティブをロックすることと同等です。
synchronized void mymethod() { ... }
void mymethod() {
synchronized (this) { ... }
}
静的メソッドの場合、クラスはロックされます。
class MyClass {
synchronized static mystatic() { ... }
static mystaticeq() {
syncrhonized (MyClass.class) { ... }
}
}
同期されたブロックの場合、null
オブジェクト以外の任意のオブジェクトをロックとして使用できます。
synchronized (mymap) {
mymap.put(..., ...);
}
スコープをロックする
同期されたメソッドの場合、ロックはメソッドスコープ全体で保持されますが、synchronized
ブロック内では、ロックはそのブロックスコープ(クリティカルセクションとも呼ばれます)の間のみ保持されます。実際には、JVMは、synchronized
安全に実行できることが証明できる場合、ブロック実行から一部の操作を削除することによって最適化することが許可されています。
同期された方法は省略形です。これ:
class Something {
public synchronized void doSomething() {
...
}
public static synchronized void doSomethingStatic() {
...
}
}
これは、すべての意図と目的において、これと同等です。
class Something {
public void doSomething() {
synchronized(this) {
...
}
}
public static void doSomethingStatic() {
synchronized(Something.class) {
...
}
}
}
Something.class
(クラスのクラスオブジェクトはどこにありますかSomething
。)
したがって、実際、同期ブロックを使用すると、ロックについてより具体的になり、いつ使用するかについてよりきめ細かくすることができますが、それ以外は違いはありません。
はい、それは1つの違いです。もう1つは、以外のオブジェクトのロックを取得できることですthis
。
主な違いは次のとおりです。同期するメソッドを宣言すると、メソッドの本体全体が同期されます。ただし、同期ブロックを使用する場合は、メソッドの「クリティカルセクション」だけを同期ブロックで囲み、残りのメソッドをブロックから除外することができます。
メソッド全体がクリティカルセクションの一部である場合、事実上違いはありません。そうでない場合は、クリティカルセクションのみの周りに同期ブロックを使用する必要があります。同期されたブロックに含まれるステートメントが多いほど、全体的な並列処理が少なくなるため、それらを最小限に抑える必要があります。
同期されたメソッドは、メソッドが含まれているオブジェクトインスタンスをロックします。
同期されたブロックは任意のオブジェクトをロックできますが、通常はインスタンス変数として定義されたミューテックスオブジェクトです。これにより、動作中のロックをより細かく制御できます。
私の考えでは、同期ブロックがスコープ内でよりローカライズされている可能性があり、したがってロックの時間が短くなることを除いて、2つの間に違いはありませんか?
はい。あなたが正しいです。メソッドとは異なりsynchronized
、同期されたステートメントは、組み込みロックを提供するオブジェクトを指定する必要があります。
Javaチュートリアルの例:
public void addName(String name) {
synchronized(this) {
lastName = name;
nameCount++;
}
nameList.add(name);
}
同期されたステートメントは、きめ細かい同期で並行性を向上させるのにも役立ちます。以下のユースケースについては、同じチュートリアルページで良い例を見つけることができます。
たとえば、クラスMsLunch
に2つのインスタンスフィールドc1とc2があり、これらが一緒に使用されることはないとします。これらのフィールドのすべての更新はである必要がありますがsynchronized
、c1の更新がc2の更新とインターリーブされるのを防ぐ理由はありません。そうすると、不要なブロッキングが作成されるため、同時実行性が低下します。同期メソッドを使用したり、これに関連付けられたロックを使用したりする代わりに、ロックを提供するためだけに2つのオブジェクトを作成します。
そして、静的メソッドのロックの場合、ロックは何で行われますか?ロックオンクラスの意味は何ですか?
この場合、スレッドはクラスに関連付けられたClassオブジェクトの組み込みロックを取得します。したがって、クラスの静的フィールドへのアクセスは、クラスのインスタンスのロックとは異なるロックによって制御されます。
メソッドを同期(非static
)として作成する場合:
synchronized
同じオブジェクトに対するメソッドの2つの呼び出しがインターリーブすることはできません。1つのスレッドがオブジェクトの同期メソッドを実行している場合、同じオブジェクトブロックの同期メソッドを呼び出す他のすべてのスレッドは、最初のスレッドがオブジェクトで完了するまで実行を一時停止します。
次のようにメソッドを作成する場合static synchronized
:
static synchronized
同じクラスの異なるオブジェクトに対するメソッドの2つの呼び出しがインターリーブすることはできません。1つのスレッドがクラスAのオブジェクトのメソッドを実行している場合、最初のスレッドがメソッドの実行を完了するまで、クラスAブロックのオブジェクトのいずれかでメソッドstatic synchronized
を呼び出す他のすべてのスレッド(実行の一時停止)。static synchronized
このSEの質問では、同期のより良い代替案を見つけます。