我正在研究几个死锁示例,并且在使用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();
}
}
由竞赛条件引起。
[System.out.format(...);
比System.out.println(...)
慢得多。
使用println()
,要打印的字符串是由调用方构建的,因此println()
要做的就是打印该字符串。
使用format()
(或printf()
),将在方法内部构建要打印的字符串,而该方法具有同步锁。此外,该方法还必须解析格式字符串,这种复杂性是println()
的简单字符串连接所不具备的。
因此,对于format()
,代码足够慢,以至于两个线程无法同时输入方法。
使用println
,代码会更快,因此两个线程同时进入方法的可能性要小得多。