4

I'm learning to write better multi-threaded programs, thread-safe and deterministic. I came across this piece of code

// File Name : Callme.java
// This program uses a synchronized block.
  class Callme {
     void call(String msg) {
        System.out.print("[" + msg);
        try {
           Thread.sleep(1000);
        } catch (InterruptedException e) {
           System.out.println("Interrupted");
        }
        System.out.println("]");
     }
  }

  // File Name : Caller.java
  class Caller implements Runnable {
     String msg;
     Callme target;
     Thread t;
     public Caller(Callme targ, String s) {
        target = targ;
        msg = s;
        t = new Thread(this);
        t.start();
     }

     // synchronize calls to call()
     public void run() {
        synchronized(target) { // synchronized block
           target.call(msg);
        }
     }
  }
  // File Name : Synch.java
  public class Synch {
     public static void main(String args[]) {
        Callme target = new Callme();
        Caller ob1 = new Caller(target, "Hello");
        Caller ob2 = new Caller(target, "Synchronized");
        Caller ob3 = new Caller(target, "World");

        // wait for threads to end
        try {
           ob1.t.join();
           ob2.t.join();
           ob3.t.join();
        } catch(InterruptedException e) {
           System.out.println("Interrupted");
        }
     }
  }

which produces the following output(tried it ~100 times)

[Hello]
[World]
[Synchronized]

So my first question is, is this output guaranteed? I also observed that if I change sleep to 100 it still produces the same output, but if I change sleep to 10 the output changes to

[Hello]
[Synchronized]
[World]

Second question is, If it's guaranteed, why? Last but not the least, Why this output? I expected it to be

[Hello]
[Synchronized]
[World]
4

4 に答える 4

2

いいえ、出力は保証されません。

于 2013-06-19T19:15:16.047 に答える
1

出力順序は保証されていません。一定の時間にスレッドが CPU を割り当てる必要がある OS によって決定されるため、出力は完全にランダムです。スレッド時間を CPU に割り当てるアルゴリズムは非決定論的です。

コードで Hello, Synchronized, World をこの順序で出力するには、次のように変更する必要がありますSynch

Caller ob1 = new Caller(target, "Hello");
ob1.t.join();
Caller ob2 = new Caller(target, "Synchronized");
ob2.t.join();
Caller ob3 = new Caller(target, "World");
ob3.t.join();

synchronizedまた、run メソッドを呼び出すスレッドは 1 つだけなので、(記述されているように) ブロックは必要ありません。またmsg、読み取りのみで書き込みは行われないため、問題が発生することはありません。また、callメソッド ontargetによって状態が変化することはありませんtarget

于 2013-06-19T19:42:28.180 に答える