web-dev-qa-db-ja.com

同じオブジェクト内の複数の同期されたメソッドを同時に実行できます

クラスに複数のsynchronizedメソッド(両方staticinstance)がある場合、私が知る限り、Javaは一度に実行するそのようなメソッドは1つだけです。しかし、スレッドがオブジェクトインスタンス(またはクラス)のロックを取得した場合、そのオブジェクト内でsynchrozedメソッドに入り、同じオブジェクトの別の同期されたメソッドを呼び出します。私は言うことを意味します:

Class AA  
{  
 ..  
 ..  
synchronized void X()  
{  
  Y();  
}

synchronized void Y()  
{  
 ..  
 ..  
}  

メソッドXを実行しているスレッドが永久にブロックすることはありますか? JavaはメソッドXとメソッドYの両方を同時に実行することを許可しないので?

7
Yeasir

Javaでは、synchronizedロックは 再入可能 です。

あるいは、スレッドがオブジェクトのロックをすでに保持している場合は、それ自体で待機する必要はありません。

12
ratchet freak

synchronizedのドキュメントを注意深く読むと、スレッドがロックを取得すると、必要なだけ何度でも再取得できることが明示されていることがわかります。

Java言語仕様によると:

8.4.3.6項「同期メソッド」は、synchronizedキーワードがモニターを取得することを示しています。参照: http://docs.Oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.4.3.6

「17.1同期」のセクションでは、スレッドtが特定のモニターを複数回ロックする可能性があると述べています。 http://docs.Oracle.com/javase/specs/jls/se8/html/jls-17.html#jls-17.1 を参照してください

したがって、スレッドがロックを取得した場合に待機する必要があるのは、otherスレッドのみです。同じスレッドが待機することなく、ロックを再取得できます。

9
Mike Nakis

Java同期は、同期されたメソッドのインスタンスに再帰的ロックを使用します。これは、各インスタンスに再帰的ロックがあり、@ synchronizedがその再帰的ロックをロックするようなものです(JVMは明らかにより賢い方法を使用しています)。したがって:

  1. 任意の数のスレッドが異なるオブジェクトに対して@synchronizedを使用できます。
  2. 1つのスレッドが同じオブジェクトに対して@synchronizedを複数回使用できます。
  3. 1つのスレッドは、他のスレッドによって@synchronizedされていない任意の数のオブジェクトに対して@synchronizedを使用できます。

@synchronizedクラスメソッドの場合、クラス自体の再帰的ロックが使用されます。クラスはファーストクラスオブジェクトであるため、上記と同じルールが適用されます。

Javaでは、このようなメソッドを一度に1つだけ実行できます

まあ、それは絶対に真実ではありません。まず、10個のスレッドが10個の異なるインスタンスの10個の同期されたメソッドを呼び出すことができ、それらすべてを最初に実行できます。同期された各メソッドは、他のインスタンスの他の同期されたメソッドを呼び出すことができ、@ synchronizedメソッドで使用されない限り、これも機能します。また、各@synchronizedメソッドは、同じインスタンスの@synchronizedメソッドを好きなだけ再帰的に呼び出すことができます。

制限は次のとおりです。2つのスレッドが同じインスタンスの@synchronizedメソッドを同時に実行したり、同じクラスの@synchronizedクラスメソッドを同時に実行したりすることはできません。

0
gnasher729