1

私は簡単なコードを持っています:

public class testing {
    private static Object objToSync = new Object();

    public static void main(String[] args) {
        String obj1 = null;
        synchronized(objToSync){
            System.out.println("something one");                    
            doSomething();
            System.out.println("something three ");         
        }

        doSomething();      
    }

    private static void doSomething() {
        synchronized(objToSync){
            System.out.println("something two");
        }       
    }

私はいくつかのものを読みましたが、まだこれと混同しています。メインの doSomething が呼び出されるのはなぜですか? 同期オブジェクトのロックが解除されるまで待つことは想定されていませんか? 私が愚かに聞こえたらごめんなさい、私はただ混乱しています。

4

4 に答える 4

11

同期オブジェクトのロックが解除されるまで待つことは想定されていませんか?

ロックはthreaddoSomethingによって保持されるため、2 回 ( in への最初の呼び出しの場合) 同期しているという事実mainは問題ではなく、同じスレッド上にあります。その後、別のsynchronizedスレッドが でブロックに入ろうとするとobjToSync、そのスレッドは、このスレッドがすべてのロックを解放するまで待機します。

あなたのコードはこれを行います:

  1. 入るmain
  2. objToSyncオブジェクトの現在のスレッドのロックを取得します
  3. 「何か」を出力する
  4. 電話doSomething
  5. 現在のスレッドの 2 番目のロックを取得するobjToSync
  6. 出力「何か 2」
  7. 現在のスレッドの 2 番目のロックを解放します。objToSync
  8. から戻るdoSomething
  9. 「something three」を出力する
  10. 現在のスレッドの最初のロックを解放しますobjToSync
  11. 電話doSomething
  12. で新しいロックを (同じスレッドに対して) 取得します。objToSync
  13. 出力「何か 2」
  14. そのロックを解除
  15. から戻るdoSomething
  16. から戻るmain

2 つのスレッドを使用した例を次に示します。

public class SyncExample {

    private static Object objToSync = new Object();

    public static final void main(String[] args) {
        Thread second;

        System.out.println("Main thread acquiring lock");
        synchronized (objToSync) {
            System.out.println("Main thread has lock, spawning second thread");
            second = new Thread(new MyRunnable());
            second.start();
            System.out.println("Main thread has started second thread, sleeping a moment");
            try {
                Thread.currentThread().sleep(250);
            }
            catch (Exception e) {
            }
            System.out.println("Main thread releasing lock");
        }
        System.out.println("Main thread sleeping again");
        try {
            Thread.currentThread().sleep(250);
        }
        catch (Exception e) {
        }
        System.out.println("Main thread waiting for second thread to complete");
        try {
            second.join();
        }
        catch (Exception e) {
        }
        System.out.println("Main thread exiting");
    }

    static class MyRunnable implements Runnable {

        public void run() {
            System.out.println("Second thread running, acquiring lock");
            synchronized (objToSync) {
                System.out.println("Second thread has lock, sleeping a moment");
                try {
                    Thread.currentThread().sleep(250);
                }
                catch (Exception e) {
                }
                System.out.println("Second thread releasing lock");
            }
            System.out.println("Second thread is done");
        }
    }
}

出力:

ロックを取得するメインスレッド
メイン スレッドにロックがあり、2 番目のスレッドが生成されます
メイン スレッドが 2 番目のスレッドを開始しました。しばらくスリープ状態です
2 番目のスレッドが実行中、ロックを取得中
主糸ゆるめロック
メインスレッドが再びスリープ状態に
2 番目のスレッドがロックされています。しばらくスリープ状態です
2 番目のスレッドの完了を待機しているメイン スレッド
二番糸緩めロック
2番目のスレッドが完了しました
メインスレッドの終了
于 2012-07-03T16:59:55.873 に答える
5

ロックはreentrant、一部のスレッドがロックを所有している場合、そのロックに基づいて他の同期ブロックに入ることができるためです。あなたの場合、スレッド(メイン)が1つしかなく、彼はこのようなことをしています

synchronized(objToSync){
    System.out.println("something one");                    
    synchronized(objToSync){
        System.out.println("something two");
    }
    System.out.println("something three");
}
于 2012-07-03T17:05:57.100 に答える
2

ロックは、同じスレッドの再入可能です。つまり、オブジェクトのロックを取得したスレッドは、オブジェクトの this およびその他の同期メソッド (または、この例のようなアトミック ステートメント) にアクセスできます。このスレッドは、いったんロックを取得すると、再度ロックを取得する必要はありません。

于 2012-07-03T17:10:45.280 に答える
1

これは、プログラムに 1 つのスレッド (メイン スレッド) しかないためです。

于 2012-07-03T17:00:22.393 に答える