web-dev-qa-db-ja.com

2つの同期されたメソッドを同時に実行しますか

私には4つの方法があります(m1m2m3およびm4)クラスで。方法 m1m2およびm3synchronizedメソッドです。また、4つのスレッドがありますt1t2t3およびt4それぞれ。

t1アクセスm1メソッド(同期メソッド)、可能性ありt2スレッドアクセスm2メソッド(同期メソッド)を同時に?そうでない場合、t2の状態はどうなりますか?

32
Tony

t1がm1メソッド(同期メソッド)にアクセスする場合、t2スレッドはm2メソッド(同期メソッド)に同時にアクセスできますか?

synchronizedキーワードはオブジェクトレベルに適用され、1つのスレッドのみがオブジェクトのロックを保持できます。同じオブジェクトについて話している限り、no、_t2_は_t1_が解放するのを待ちます_m1_に入ったときにロックが取得されました。

ただし、スレッドはObject.wait()を呼び出すことにより、メソッドから戻ることなくロックを解放できます。

そうでない場合、t2の状態はどうなりますか?

それはしっかりと座って、_t1_がロックを解放するのを待ちます(メソッドから戻るか、Object.wait()を呼び出します)。具体的には、 BLOCKED state になります。

モニターロックの待機中にブロックされたスレッドのスレッド状態。ブロック状態のスレッドは、_Object.wait_。を呼び出した後、モニターロックが同期ブロック/メソッドに入るか、同期ブロック/メソッドに再入するのを待機しています。

サンプルコード:

_public class Test {

    public synchronized void m1() {
        try { Thread.sleep(2000); }
        catch (InterruptedException ie) {}
    }

    public synchronized void m2() {
        try { Thread.sleep(2000); }
        catch (InterruptedException ie) {}
    }

    public static void main(String[] args) throws InterruptedException {
        final Test t = new Test();
        Thread t1 = new Thread() { public void run() { t.m1(); } };
        Thread t2 = new Thread() { public void run() { t.m2(); } };

        t1.start();
        Thread.sleep(500);

        t2.start();
        Thread.sleep(500);

        System.out.println(t2.getState());
    }
}
_

出力:

_BLOCKED
_
45
aioobe

メソッドが同じモニターで同期されている場合、異なるスレッドで同時に実行することはできません。 2番目のスレッドがモニターエントリ(この場合は同期メソッドの開始)に到達すると、最初のスレッドがモニターを解放するまでブロックされます。

この場合、ブロックされたスレッドの実際の状態は、jconsoleによって報告され、Java.lang.Thread.State: WAITING (on object monitor)のようになります。

すべてのメソッドが通常のインスタンスメソッドであると仮定すると、それらは同じモニターを共有します同じオブジェクトで呼び出された場合。つまり、次のようなものがある場合:

_// Thread 1
A a1 = new A();
a1.m1();

// Thread 2
A a2 = new A();
a2.m2()
_

この場合、2番目のスレッドはメソッドを呼び出すことができます。これは、notによってロックされている_a2_オブジェクトの暗黙的なモニターを取得しようとしているためです。スレッド1。ただし、スレッド2がa1.m2()を呼び出そうとすると、スレッド1がm1()の実行を終了するまでブロックされます。

静的メソッドがある場合、それらはクラス自体の明示的なモニターを取得するため(私の仮定の名前付けの場合は_A.class_)、anyインスタンスによってブロックされませんメソッドの呼び出し。

11
Andrzej Doyle

いいえ、できませんでした。それがsynchronizedの唯一のポイントです:異なるスレッドがこれらのことを同時に実行することはできません(同じスレッドが同時に実行するのを防ぐ必要はありません。単一のスレッドが並行して何もできないためです。待機中のスレッドの状態は「ロックを待機中」です。 (十分に最新のJVMでは、正しい方法で尋ねれば、実際にこの状態をコンソールに表示できます。)

4
Kilian Foth

T1がm1メソッド(同期メソッド)にアクセスする場合、t2スレッドはm2メソッド(同期メソッド)に同時にアクセスできますか?

いいえ。スレッドt2は、スレッドt1がロックを解放するのを待ちます。同じ例で、t2は同期されていないメソッドm4にアクセスできます。

ロックイン 同期 メソッド

すべてのオブジェクトには、固有のロックが関連付けられています。慣例により、オブジェクトのフィールドへの排他的かつ一貫したアクセスを必要とするスレッドは、オブジェクトにアクセスする前にオブジェクトの組み込みロックを取得し、それらが完了したら組み込みロックを解放する必要があります

スレッドが同期メソッドを呼び出すと、スレッドはそのメソッドのオブジェクトの組み込みロックを自動的に取得し、メソッドが戻ったときにそれを解放します。キャッチされていない例外が原因でリターンが発生した場合でも、ロック解除が発生します

2番目のクエリに戻ります。

そうでない場合、t2の状態はどうなりますか?

スレッドt2はブロック状態にあり、スレッドt1がロックを解放するのを待っています。

From Java documentation page:

synchronizedメソッドを作成すると2つの効果があります。

まず、同じオブジェクトで同期されたメソッドの2つの呼び出しがインターリーブすることはできません。 1つのスレッドがオブジェクトの同期メソッドを実行している場合、同じオブジェクトブロックの同期メソッドを呼び出す他のすべてのスレッドは、最初のスレッドがオブジェクトで完了するまで実行を一時停止します。

次に、同期メソッドが終了すると、同じオブジェクトの同期メソッドの後続の呼び出しとの発生前の関係が自動的に確立されます。これにより、オブジェクトの状態への変更がすべてのスレッドに表示されることが保証されます

1
Aditya W