1

同期ブロックについて疑問があります。以下のコードを実行すると、次のように出力されます。

Inside run=>thread 2
Inside run=>thread 1
Inside run=>thread 1
Inside run=>thread 2
Inside run=>thread 2
Inside run=>thread 1
Inside run=>thread 2
Inside run=>thread 1
Inside run=>thread 1
Inside run=>thread 2

1 つのスレッドのみが最初に同期ブロックを実行し、次に 2 番目のスレッドのみが同期ブロックにアクセスするため、出力を期待していました。私は概念を間違って理解しているのでしょうか?

 package com.blt;

    public class ThreadExample implements Runnable {
        public static void main(String args[])
        {


            System.out.println("A");
            Thread T=new Thread(new ThreadExample());
            Thread T1=new Thread(new ThreadExample());
            System.out.println("B");
            T.setName("thread 1");
            T1.setName("thread 2");
            System.out.println("C");
            T.start();
            System.out.println("D");
            T1.start();
        }


     synchronized public void run()
    {
        for(int i=0; i<5; i++)
        {
            try
            {
             System.out.println("Inside run=>"+Thread.currentThread().getName());
             Thread.currentThread().sleep(2000);
            }
             catch(InterruptedException e)
            {
                e.printStackTrace();
            }
          }  
    }
    }
4

5 に答える 5

4

各スレッドは異なるオブジェクトで同期しています。そうです、彼らはお互いを締め出すことはありません。しかし、もっと重要なことは、このrunメソッドは同期修飾子なしRunnableでインターフェイス用に定義されているため、同期修飾子を追加しないでください(すでにご覧のとおり、思ったほどの効果はありませんでした)。

覚えておくべき重要なことは、メソッドで同期修飾子を使用する場合、次のことです。

public synchronized void someMethod();

実質的にはを使用するのと同じですsynchronized(this)。どちらの場合も、オブジェクトモニターをロックしています。複数のオブジェクトがある場合は、複数のモニターがあります。

これはあなた自身の例の修正版であり、あなたが期待したようにもっとうまくいくでしょう。共通のオブジェクトモニター(この場合はクラス自体)を使用するため、同期は期待どおりに機能します。

public class ThreadExample implements Runnable {
    public static void main(String args[]) {
        System.out.println("A");
        Thread T = new Thread(new ThreadExample());
        Thread T1 = new Thread(new ThreadExample());
        System.out.println("B");
        T.setName("thread 1");
        T1.setName("thread 2");
        System.out.println("C");
        T.start();
        System.out.println("D");
        T1.start();
    }

    public void run() {
        synchronized (ThreadExample.class) {
            for (int i = 0; i < 5; i++) {
                try {
                    System.out.println("Inside run=>"
                            + Thread.currentThread().getName());
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
于 2013-02-11T10:15:36.137 に答える
3

あなたの問題は、同じモニターでロックされていない場合、2 つの同期ブロックが相互に排他的ではないことです。

同期されたメソッドはthisモニターでロックされることに注意してください。コードは次と同等です。

 public void run() {
    synchronized(this) {
        //your code here
    }
 }

の 2 つのインスタンスを作成するためThreadExample、それぞれに異なるthis.

両方のスレッドで同じロックを使用することで問題を解決できます。次に例を示します。

 public void run() {
    synchronized(ThreadExample.class) {
        //your code here
    }
 }

またはさらに良いことに、 QuoiThreadExampleで指摘されているように のインスタンスを 1 つだけ作成します。

于 2013-02-11T10:17:00.033 に答える
1

の2つのオブジェクトを作成しThreadExampleたので、各スレッドには異なるsynchronizedメソッドがあります。

単一のオブジェクトを作成し、スレッドへの参照を渡すと、同期された効果が表示されます。:)

ThreadExample thex = new ThreadExample();
Thread T=new Thread(thex);
Thread T1=new Thread(thex);

ここでは、両方のスレッドが同じsynchronizedメソッドを使用します。

于 2013-02-11T10:16:02.093 に答える
0

ええと、各スレッドの実行メソッドを同期しています。Thread1 は Thread2 の run メソッドを実行しようとしません。そのため、まったく同期しないのと事実上同じです。

于 2013-02-11T10:17:40.007 に答える
0

クラスの 2 つのインスタンスを作成し、クラスで同期しているため、共通のロックがないため、それらは独立して実行されます。それらは別々に実行され続けます。

于 2013-02-11T10:18:20.520 に答える