使用System.out.format和System.out.println进行多线程 [英] Mutithreading with System.out.format and System.out.println

查看:228
本文介绍了使用System.out.format和System.out.println进行多线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在Oracle Java教程中遇到了示例多线程方案中的死锁.

I came across this example on Oracle's Java Tutorial describing Deadlock in multi threading scenarios.

因此,在此示例中,我在第17行和第18行进行了以下更改.

So in this example I made following change at line 17 and line 18.

public class DeadLock {
  static class Friend {
    private final String name;

    public Friend(String name) {
        this.name = name;
    }

    public String getName() {
        return this.name;
    }

    public synchronized void bow(Friend bower) {
        //My Changes
        //System.out.format("%s: %s" + " has bowed to me!%n", this.name, bower.getName()); //Line 17
         System.out.println(this.name + ": " + bower.getName() + " has bowed to me!"); //Line 18
        bower.bowBack(this);
    }

    public synchronized void bowBack(Friend bower) {
        System.out.format("%s: %s" + " has bowed back to me!%n", this.name, bower.getName());
    }
  }

  public static void main(String[] args) {
    final Friend alphonse = new Friend("Alphonse");
    final Friend gaston = new Friend("Gaston");
    new Thread(new Runnable() {
        @Override
        public void run() {
            alphonse.bow(gaston);
        }
    }).start();

    new Thread(new Runnable() {
        @Override
        public void run() {
            gaston.bow(alphonse);
        }
    }).start();
  }
}

进行这些更改后,程序将成功终止,而不会导致死锁,并在输出后进行打印

Upon doing these changes the program terminated successfully without causing deadlock and printed following output

Alphonse: Gaston has bowed to me!
Gaston: Alphonse has bowed back to me!
Gaston: Alphonse has bowed to me!
Alphonse: Gaston has bowed back to me!

所以我的问题是-为什么会这样表现? println语句如何防止死锁?

So my question is- why did it behave like this? How did the println statement prevent the deadlock?

推荐答案

使用System.out.print还是System.out.format并没有什么不同:它们基本上是在做相同的事情.

There is no difference in whether you use System.out.print or System.out.format: they're basically doing the same thing.

如果在Alphonse.bow(Gaston)bower.bowBack(Alphonse)的开始之间开始执行Gaston.bow(Alphonse),则在这里发生死锁(反之亦然):两个线程正在等待另一个线程持有的监视器,因此发生死锁.

The deadlock occurs here if execution of Gaston.bow(Alphonse) is started between the start of Alphonse.bow(Gaston) and bower.bowBack(Alphonse) (or vice versa): the two threads are waiting for a monitor held by the other, and thus deadlock occurs.

这种情况不一致地发生,因为它取决于细微的计时问题,具体取决于线程的调度方式-Alphonse.bowbower.backBack(Alphonse)可能在执行Gaston.bow之前完成,因此看起来好像没有僵局.

This happens inconsistently, because it depends upon a subtle timing issue, depending upon how the threads are scheduled - it is possible that Alphonse.bow and bower.backBack(Alphonse) complete before Gaston.bow is executed, so it looks like there is no deadlock.

解决此问题的经典方法是对锁获取进行排序,以便第一个相同的锁每次都首先获取;这样可以避免出现死锁的情况:

The classic way to fix this is to order the lock acquisition, so that the first the same lock is acquired first every time; this prevents the possibility of deadlock:

public void bow(Friend bower) {  // Method no longer synchronized.
  int firstHash = System.identityHashCode(this);
  int secondHash = System.identityHashCode(bower);

  Object firstMonitor = firstHash < secondHash ? this : bower;
  Object secondMonitor = firstHash < secondHash ? bower : this;
  synchronized (firstMonitor) {
    synchronized (secondMonitor) {
      // Code free (*) of deadlocks, with respect to this and bower at least.
    }
  }
}

(*)并非相当保证没有死锁,因为System.identityHashCode可以为不同的对象返回相同的值.但这不太可能.

(*) It's not quite guaranteed to be deadlock free, since System.identityHashCode can return the same value for distinct objects; but that's reasonably unlikely.

它是生日悖论的应用:如果您只有两个显示器,发生碰撞的几率约为10 ^ -18;但是如果您有超过77,000台显示器,则很可能发生碰撞.

It's an application of the Birthday paradox: if you've got just two monitors, the chance of collision is something like 10^-18; but if you've got >77k monitors, a collision is more likely than not.

这篇关于使用System.out.format和System.out.println进行多线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆