为什么输出来自不同而不是每次同步块的(why output comes different ever

2019-09-17 07:08发布

class Callme {
   void call(String msg) {
      System.out.print("[" + msg);
      try {
         Thread.sleep(10);
      } catch (InterruptedException e) {
         System.out.println("Interrupted");
      }
      System.out.println("]");
   }
}


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();
      System.out.println("rahul");
      System.out.println("rahul");
      System.out.println("rahul");
      System.out.println("rahul");
      System.out.println("rahul");
      System.out.println("rahul");
      System.out.println("rahul");
      System.out.println("rahul");
      System.out.println("rahul");
      System.out.println("rahul");
   }

   // synchronize calls to call()
   public void run() {
      synchronized(target) { // synchronized block
         target.call(msg);
      }
   }
}

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");
      }
   }
}

在这个节目时,我使用的是System.out.print不同步的块(“拉胡”),它完美的打印输出,但是当我把SOP的这些不必要的声明(“拉胡”)输出被扭曲为什么会发生,而不是同步?

Answer 1:

我将假设System.out.println消息引起您的3个Caller消息更改订单:

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

这里没有保证的顺序。 即使"Hello" Caller对象先构造,这并不意味着它run()方法实际上将首先执行。 还有一个比赛进行到synchronized内每个线程块。 在"World"的字符串可打印的第一为例。

通过添加一系列System.out.println("rahul"); 调用,它听起来就像你正在影响到程序的时间。 底层PrintStream对象是同步的,因此它会影响在其他线程锁定,即使他们是在另一对象锁定。 任何同步跨越内存屏障导致线程之间的缓存刷新和内存复制,并且可以影响其运行的顺序,速度等。如果你运行你的程序1000次,你会看到许多不同的输出组合。 这就是竞态条件的性质 - 它们是不可预测的。



Answer 2:

每个单独System.out.println()在内部同步的,所以无论从单个输出println()调用应该得到乱码。

然而,有多个没有同步调用println() 。 如果多个线程同时写入同一个打印流,在他们的邮件将会出现的相对顺序无法得到保证。

如果你需要一个特定的顺序,你必须在自己的线程同步。



Answer 3:

你开始从构造一个线程,通过这个实例到线程。 来电尚未完全构造它的成员变量可能还没有被run方法初始化。

额外的println被允许可以看到的bug。

可运行应该定义工作,并调用代码应该处理的线程。 可运行不应该运行自己。

你也应该同步对最终的变量。

class Caller implements Runnable {
   final String msg;
   final Callme target;

   public Caller(Callme targ, String s) {
      target = targ;
      msg = s;
      System.out.println("rahul");
      System.out.println("rahul");
      System.out.println("rahul");
      System.out.println("rahul");
      System.out.println("rahul");
      System.out.println("rahul");
      System.out.println("rahul");
      System.out.println("rahul");
      System.out.println("rahul");
      System.out.println("rahul");
  }

  // synchronize calls to call()
  public void run() {
     synchronized(target) { // synchronized block
        target.call(msg);
     }
  }
}

class Synch {
 public static void main(String args[]) {
  Callme target = new Callme();
  Thread ob1 = new Thread(Caller(target, "Hello"));
  Thread ob2 = new Thread(Caller(target, "Synchronized"));
  Thread ob3 = new Thread(Caller(target, "World"));

  obj1.start();
  obj2.start();
  obj3.start();

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

}}



文章来源: why output comes different everytime instead of synchronized block