【问题标题】:Role of System.out.format in Oracle's deadlock exampleOracle死锁示例中System.out.format的作用
【发布时间】:2020-04-17 00:00:34
【问题描述】:

我正在查看几个死锁示例,并在使用 Oracle 示例时发现了一些有趣的事情:https://docs.oracle.com/javase/tutorial/essential/concurrency/deadlock.html

如果您替换此行: System.out.format("%s: %s" + " 已经向我鞠躬了!%n", this.name, bower.getName());

与: System.out.println(this.name + "已经向我鞠躬了!" + bower.getName());

不会再触发死锁。

谁能解释一下原因?

从上面的链接中添加代码以供将来参考:

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) {
            System.out.format("%s: %s"
                + "  has bowed to me!%n", 
                this.name, bower.getName());
            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() {
            public void run() { alphonse.bow(gaston); }
        }).start();
        new Thread(new Runnable() {
            public void run() { gaston.bow(alphonse); }
        }).start();
    }
}

【问题讨论】:

  • 请在问题中包含相关代码。时间链接坏了。

标签: java deadlock


【解决方案1】:

这是由竞态条件引起的。

System.out.format(...);System.out.println(...) 慢得多。

使用println(),要打印的字符串由调用者构建,所以println() 所要做的就是打印该字符串。

使用format()(或printf()),要打印的字符串在方法内部构建,而方法具有同步锁。此外,该方法必须解析格式字符串,println() 不存在复杂性,因为它是简单的字符串连接。

因此,使用format(),代码足够慢,足以让 2 个线程同时进入方法。

使用println,代码更快,所以两个线程同时进入方法的概率要小很多。

【讨论】:

  • 那么System.out.format 版本是否可以在没有死锁的情况下运行?以防计算机足够快。
  • @samabcde 是的。插入例如两个线程之间的Thread.sleep(500); start() 调用main()。这使得线程 #2 太慢而无法导致竞争条件。
  • 所以在不更改代码的情况下,System.out.format 版本应该总是(或几乎总是)运行 with 死锁吗?我只是很好奇示例的作者为什么选择System.out.format,而不是添加Thread.sleep
  • @samabcde format() 足够慢,以至于出现竞争条件的概率非常非常高。这篇文章实际上是这样说的:“当死锁运行时,极有可能两个线程都会阻塞......” ---至于为什么,你要问作者。
  • 好的,谢谢你的解释。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-06
  • 1970-01-01
相关资源
最近更新 更多