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オブジェクトの固有のロックを取得します。したがって、クラスの静的フィールドへのアクセスは、クラスのインスタンスのロックとは異なるロックによって制御されます。
メソッドを synchronized (non static
)とすると、次のようになります。
同じオブジェクトでsynchronized
メソッドを2回呼び出すことはできません。 1つのスレッドがオブジェクトの同期メソッドを実行しているとき、同じオブジェクトの同期メソッドを呼び出す他のすべてのスレッドは、最初のスレッドがオブジェクトで完了するまでブロックします(実行を中断します)。
メソッドをstatic synchronized
として作成した場合:
同じクラスの異なるオブジェクトでstatic synchronized
メソッドを2回呼び出すことはできません。 1つのスレッドがクラスAのオブジェクトに対してstatic synchronized
メソッドを実行している場合、クラスAのオブジェクトのいずれかでstatic synchronized
メソッドを呼び出すすべてのスレッドは、メソッドの実行。
このSEの質問で、同期のより良い代替案を見つけます。
同期されたメソッドは、メソッドが含まれているオブジェクトインスタンスをロックします。
同期されたブロックが任意のオブジェクトをロックできる場合-通常、インスタンス変数として定義されたミューテックスオブジェクト。これにより、操作中のロックをより詳細に制御できます。