4

sleep() は現在の同期メソッド/ブロックをロックすると聞きましたが、ここで、スレッド 1 で sleep() を呼び出すと、スレッド 2 は同じブロックにアクセスできますか? 誰でも説明できますか?

Main.java

public class Main {     
    public static void main(String args[])
    {
        Thread1 t1 = new Thread1();
        Thread2 t2 = new Thread2();
        System.out.println("going to start t1");
        t1.start();
        System.out.println("going to start t2");
        t2.start();

    }

}

================================================== ===================

Thread1.java

public class Thread1 extends Thread{

    public void run() { 
        Syncc s1 = new Syncc();
        s1.me("T1:");
    }   

}

================================================== ===================

Thread2.java

public class Thread2 extends Thread{

    public void run() { 
        Syncc s2 = new Syncc();
        s2.me("T2:");
    }   
}

================================================== ===================

同期.java

public class Syncc{

    public void me(String s){
        synchronized(this){
        for(int i=0; i<=5; i++)
        {
            System.out.println(s+" "+" "+i);
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {              
                e.printStackTrace();
            }
        }
    }
}
}

==========================================

出力:

going to start t1
going to start t2
T2:  0
T1:  0
T2:  1
T1:  1
T1:  2
T2:  2
T1:  3
T2:  3
T1:  4
T2:  4
T2:  5
T1:  5

しかし、sleep() メソッドによると、現在の同期ブロックのロックを解除するべきではありませんか? もしそうなら、出力は..

t1 を開始します t2 を開始します

T1:  0
T1:  1
T1:  2
T1:  3
T1:  4
T1:  5
T2:  0
T2:  1
T2:  2
T2:  3
T2:  4
T2:  5

つまり、スレッド 1 の実行後、スレッド 2 のみが正しく開始されますか? 問題は何ですか?

4

3 に答える 3

9

これは、Synccここで in play の 2 つの異なるインスタンスがあるためです。各スレッドには、独自の のコピーがありSynccます。

単一のインスタンスで同じことを試してください。静的コンテキストで同期して試すこともできます。

のインスタンスをシミュレート、変更Thread1、およびThread2受け入れるSyncc

public class Thread1 extends Thread {
    private Syncc syncc;

    public Thread1(Syncc syncc) {
        this.syncc = syncc;
    }

    public void run() { 
        this.syncc.me("T1:");
    }   
}

その後、次のように開始できます。

public static void main(String args[]) {
    Syncc syncc = new Syncc();

    Thread1 t1 = new Thread1(syncc);
    Thread2 t2 = new Thread2(syncc);

    System.out.println("going to start t1");
    t1.start();
    System.out.println("going to start t2");
    t2.start();
}
于 2012-06-08T09:54:18.660 に答える
2

スリープ、イールド、ジョインのルール

  • スリープは一定期間実行を遅らせるために使用され、スレッドがスリープ状態になるとロックは解放されません。

  • スリープ中のスレッドは、少なくとも sleep() メソッドの引数で指定された時間 (中断されない限り) スリープすることが保証されていますが、新しく目覚めたスレッドが実際にいつ実行に戻るかについての保証はありません。

  • sleep() メソッドは、現在実行中のスレッドの状態をスリープ状態にする静的メソッドです。あるスレッドが別のスレッドにスリープ状態を指示することはできません。

  • setPriority() メソッドは Thread オブジェクトで使用され、スレッドに 1 (低) から 10 (高) の優先度を与えますが、優先度は保証されておらず、すべての JVM が 10 の異なる優先度レベルを認識するわけではありません。同等。

  • 明示的に設定されていない場合、スレッドの優先度は、それを作成したスレッドの優先度と同じになります。

  • 同じ優先度の実行可能なスレッドがある場合、yield() メソッドは実行中のスレッドをバックアウトさせる可能性があります。これが発生するという保証はなく、スレッドがバックアウトしたときに別のスレッドが実行するように選択されるという保証もありません。スレッドが解放され、すぐに実行状態に戻ることがあります。

  • 保証に最も近いのは、スレッドが実行されているとき、通常、実行可能な状態のどのスレッドよりも優先順位が低くなることはないということです。優先順位の高いスレッドが実行可能になったときに優先順位の低いスレッドが実行されている場合、JVM は通常、実行中の優先順位の低いスレッドを横取りし、優先順位の高いスレッドを入れます。

  • あるスレッドが別のスレッドの join() メソッドを呼び出すと、現在実行中のスレッドは、参加しているスレッドが完了するまで待機します。join() メソッドは、「スレッドさん、あなたの最後に参加したいです。完了したらお知らせください。実行可能な状態に入ることができます。」と言っていると考えてください。

http://www.amazon.com/SCJP-Certified-Programmer-Java-310-065/dp/0071591060

于 2012-06-08T09:58:56.323 に答える
0

それぞれが 1 つのスレッドに対応する 2 つの Synch オブジェクトを作成しました。各オブジェクトには、自分のコピーがあります。したがって、各スレッドを開始すると、run メソッドを使用して、スレッドは関数 me の独自のコピーを呼び出します。2 つのスレッドはそのコピーに対してのみ機能するため、これはシングル スレッドのシナリオのように機能します。マルチスレッド シナリオをテストする場合は、メソッド me を静的 (クラス レベル メソッド) にして、クラス レベル ロックを適用します。

Thread1.java

public class Thread1 extends Thread{

public void run() { 
    Syncc.me("T1:");
}   

}

Thread2.java

public class Thread2 extends Thread{

public void run() { 
    Syncc.me("T2:");
}   

}

同期.java

public class Syncc{

public static void me(String s){
    synchronized(Syncc.class){
    for(int i=0; i<=5; i++)
    {
        System.out.println(s+" "+" "+i);
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {              
            e.printStackTrace();
        }
    }
}

} }

于 2012-06-08T10:11:44.540 に答える