【问题标题】:Shouldn't Java compiler force to make synchronize?Java编译器不应该强制同步吗?
【发布时间】:2013-11-22 20:05:15
【问题描述】:

考虑以下场景。

public synchronized String getData(){
    return getInfo();
}
private String getInfo(){                   
    // operation here should synchronized
    return  "Synchronize Info";
}

如果有人绕过这个操作的流程。系统可能会变得不稳定,如果Java编译器强制使getInfosynchronized这样的问题就不存在了。但是 Java 编译器并不强制这样做。现在开发人员应该负责是否制作getInfo synchronized。为什么 Java 不强制生成 getInfo synchronized

【问题讨论】:

  • 同步是有代价的。
  • @frostjogla 谁说编译器写代码?如果您不知道,请不要理会它。换个角度看比写东西要好。
  • 如果从getData() 调用,getInfo() 将被同步。或者您是在问如果有人在getData() 之外拨打getInfo() 会发生什么?
  • @Boann 是的,我的问题是当有人在外面呼叫getInfo() 时,会导致系统不稳定。

标签: java synchronized


【解决方案1】:

Java 编译器不可能有效地执行此操作。您可以发明一条规则,即同步方法只能在同步的情况下调用同一对象的方法,但除非在非常狭窄的场景中,否则它没有帮助。如果getInfo() 是公开的,getData() 可以轻松调用不同的类,该类在原始对象上回调getInfo()

此外,同步可以用于单个语句而不是整个方法,还有other locks。尝试设计编译器规则以防止在所有这些情况下使用非同步数据的同步代码将是复杂的或不可能的。

实际上,在知道只有线程在使用对象的情况下,想要调用一个方法而不需要同步成本是合法的。决定对象的哪些部分应该被锁定以及何时锁定是一个复杂的设计问题,只有人类程序员才能做到。

因此,Java 不能/不会阻止您编写不安全的代码。它不在乎。如果“系统”是指“计算机”,它不会“变得不稳定”。在最坏的情况下,那一类会是错误的。

【讨论】:

    【解决方案2】:

    来自http://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html 的 Java 文档,“同一对象上的同步方法的两次调用不可能交错”。

    换句话说,如果您调用getData,那么以后对同一对象的任何getData 调用都将等到该调用完成。因此,即使控制流移动到getInfo,系统仍然会阻止任何将来对getData 的调用,直到第一个返回,所以没有理由阻止getInfo。希望对您有所帮助!

    【讨论】:

    • 我认为关键是其他一些不同步的方法可能会意外调用getInfo(据说它对同步敏感) - 尽管我不确定 OP 期望什么.在这个我也会把同步关键字放在getInfo
    • 是的 - 在示例中,他告诉编译器 getData 中完成的工作对同步敏感,但 getInfo 不是。因此,编译器将在 getData 上强制执行它,但 getInfo 仍然可以同时运行。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-01
    • 1970-01-01
    相关资源
    最近更新 更多