5

Why is it that two synchronized blocks can't be executed simultaneously by two different threads in Java.

EDIT

public class JavaApplication4 {

    public static void main(String[] args) {
        new JavaApplication4();
    }

    public JavaApplication4() {
        Thread t1 = new Thread() {

            @Override
            public void run() {
                if (Thread.currentThread().getName().equals("Thread-1")) {
                    test(Thread.currentThread().getName());
                } else {
                    test1(Thread.currentThread().getName());
                }
            }
        };
        Thread t2 = new Thread(t1);
        t2.start();
        t1.start();

    }

    public synchronized void test(String msg) {
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException ex) {
            }
            System.out.println(msg);
        }
    }

    public synchronized void test1(String msg) {
        for (int i = 0; i < 10; i++) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException ex) {
            }
            System.out.println(msg + " from test1");
        }
    }
}
4

4 に答える 4

11

あなたの発言は誤りです。同じロックを争わない限り、同期されたブロックはいくつでも並行して実行できます。

しかし、あなたの質問が同じロックを争うブロックについてである場合、それが全体の概念の目的であるため、「なぜそうなのか」と尋ねるのは誤りです。プログラマーは相互排除メカニズムを必要synchronizedとし、Javaからを介してそれを取得します。

最後に、「コードセグメントを並列実行から相互に除外する必要があるのはなぜですか」と質問するかもしれません。その答えは、特定の方法で編成され、スレッドが構造を更新するときにのみ意味をなすデータ構造が多数あるため、構造は「壊れた」状態にあるということです。更新を行っている間。その時点で別のスレッドがやって来て、構造を読み取ろうとしたり、さらに悪いことに、それ自体を更新したりすると、すべてが崩壊します。

編集

私はあなたの例とあなたのコメントを見ました、そして今あなたを悩ませているのは明らかです:synchronizedメソッドの修飾子のセマンティクス。thisこれは、メソッドがのモニターのロックを争うことを意味します。同じオブジェクトのすべてのsynchronizedメソッドは、同じロックを求めて競合します。

于 2012-08-10T11:46:50.527 に答える
4

これが同期の全体的な概念です。オブジェクト(またはクラス)をロックしている場合、他のスレッドは同期されたブロックにアクセスできません。

Class A{

public void method1()
{
 synchronized(this)//Block 1 taking lock on Object
 {
  //do something
 }
}

public void method2()
{
 synchronized(this)//Block 2 taking lock on Object
 {
  //do something
 }
}
}

オブジェクトの1つのスレッドが同期ブロックのいずれかに入る場合、同じオブジェクトの他のすべてのスレッドは、そのスレッドが同期ブロックから出て同期ブロックのいずれかに入るのを待つ必要があります。そのようなブロックがN個ある場合、オブジェクトの1つのスレッドのみが一度に1つのブロックにのみアクセスできます。同じオブジェクトのスレッドに重点を置いていることに注意してください。異なるオブジェクトからのスレッドを処理している場合、この概念は適用されません。

また、クラスをロックしている場合、上記の概念はクラスの任意のオブジェクトに拡張されることも付け加えておきます。したがって、synchronized(this)を使用する代わりにsynchronized(A.class)、コードがJVMに指示し、スレッドが属するオブジェクトに関係なく、他のスレッドが同期ブロックの実行を終了するのを待機させます。

編集:(同期キーワードを使用して)ロックを取得しているときは、1つのブロックをロックしているだけではないことを理解してください。オブジェクトをロックしています。つまり、JVMに「ねえ、このスレッドはオブジェクト(またはクラス)の状態を変更する可能性のある重要な作業を行っているので、他のスレッドに他の重要な作業を行わせないでください」と言っているということです。重要な作業は、ここでは、1つの同期ブロックだけでなく、その特定のオブジェクト(またはクラス)をロックする同期ブロック内のすべてのコードを指します。

于 2012-08-10T11:53:42.320 に答える
0

これは絶対に真実ではありません。異なるオブジェクトのロックを処理している場合、複数のスレッドがそれらのブロックを実行できます。

   synchronized(obj1){
       //your code here
   }

   synchronized(obj2){
       //your code here
   }

上記の場合、1つのスレッドが最初に実行でき、2番目が2番目のブロックを実行できます。ここで重要なのは、スレッドが異なるロックで動作していることです。

スレッドが同じものを処理している場合、ステートメントは正しいですlock。1つのスレッドがロックを取得して実行している場合、他のスレッドは最初のスレッドがそのロックを解放するまで待機する必要があります。ロックはブロックまたはメソッドlockによって取得できます。synchronized

于 2012-08-10T11:54:35.700 に答える
0

2つのスレッドは、同じオブジェクトをロックしなくなるまで、同期されたブロックを同時に実行できます。

ブロックが異なるオブジェクトで同期されている場合...それらは同時に実行できます。

synchronized(object1){
    ...
}

synchronized(object2){
    ...
}

編集: Please reason the output for http://pastebin.com/tcJT009i

あなたの例では、同期されたメソッドを呼び出すときに、同じオブジェクトに対してロックが取得されます。2つのオブジェクトを作成してみてください。

于 2012-08-10T11:48:23.090 に答える