5

以下のコードでデッドロックが発生しないのはなぜですか? つまり、getNumber(.) を呼び出した後、クラス Test のオブジェクトをロックする必要があるため、getNumber2(.) にアクセスできないはずです。

class Test() {
    synchronized int getNumber(int i){
        return getNumber2(i);
    }

    synchronized int getNumber2(int i) {
        return i;
    }

    public static void main(String[] args) {
        System.out.println((new Test()).getNumber(100));
    }
}

出力:

100
4

2 に答える 2

20

これは、ロックが再入可能であるためです。つまり、同じスレッドによって複数回取得される可能性があります。

Javaチュートリアルから:

再入可能同期

スレッドは、別のスレッドが所有するロックを取得できないことを思い出してください。ただし、スレッドは既に所有しているロックを取得できます。スレッドが同じロックを複数回取得できるようにすると、再入可能な同期が可能になります。これは、同期されたコードが直接的または間接的に、同期されたコードも含むメソッドを呼び出し、両方のコード セットが同じロックを使用する状況を表します。再入可能な同期がなければ、同期されたコードは、スレッド自体がブロックされるのを避けるために、さらに多くの予防策を講じる必要があります。

JLS の関連部分は§17.1 です。同期:

Java プログラミング言語は、スレッド間で通信するための複数のメカニズムを提供します。これらの方法の最も基本的なものは、モニターを使用して実装される同期です。Java の各オブジェクトは、スレッドがロックまたはロック解除できるモニターに関連付けられています。一度に 1 つのスレッドだけがモニターのロックを保持できます。そのモニターをロックしようとする他のスレッドは、そのモニターのロックを取得できるまでブロックされます。スレッド t は、特定のモニターを複数回ロックする場合があります。ロックを解除するたびに、1 回のロック操作の効果が逆になります。

于 2013-03-04T14:35:41.137 に答える
4

thisスレッドが同期メソッドに入ると、ロックがオンになっていることを確認し、そうでない場合は、ロックを取得して取得できるようになるまで待機するため、デッドロックは発生しません。

あなたの場合、スレッドが2番目の同期されたメソッドに入ると、thisオブジェクトはすでにロックされているため、ブロックせずにメソッドに入ることができます。

于 2013-03-04T14:37:34.180 に答える