同步块中的字符串不变性和等待方法

时间:2013-03-04 20:22:20

标签: java string thread-safety immutability

我是java的新手,当我阅读java语言时,我有两个疑问。虽然我推荐了很多网站,但我还不是很清楚。

1)为什么字符串类是不可变的?我看到了new File(str)导致安全威胁的一些例子,但我不明白如果字符串是不可变的,它将有助于这种情况。

2)另一个疑问是为什么wait,notify和notifyall应该在synchronized块内。我知道如果不抛出illegalMonitorException。但我想知道为什么它应该在synchronized块中的技术背景,为什么不在同步块等待和通知可以有相同的行为。

请帮助我理解。

1 个答案:

答案 0 :(得分:1)

  

为什么字符串类是不可变的?

为什么字符串在Java中是不可变的问题是一个古老的问题,并且引起了很多争议。在我的书中,我会说它们是不可变的,因为它们应该是不可变的;)。这可能听起来像个警察,但让我解释一下。

最简单的说,字符串在整个地方使用,如果它们是可变的,那里需要大量的行李来制作防御性拷贝和处理同步等等。使它们成为不可变的,然后像StringBuilder / StringBuffer那样使用帮助器来改变它们是一个更好的设计选择(并且是几种语言中的常见选择,而不仅仅是Java)。

其次,除非有充分理由证明可变性,否则一切都应该是不可改变的。许多问题随着不可变类而消失(特别是与并发有关)。请参阅Effective Java:“类应该是不可变的,除非有一个很好的理由使它们变得可变。如果一个类不能成为不可变的,那么尽可能地限制它的可变性。”

第三,字符串用于Java的内部,例如类加载机制。使它们不可变使内部过程更简单,并防止出现一些安全问题。 (另一个例子,由于性能原因,字符串常量在Java中被“实例化”:http://en.wikipedia.org/wiki/String_interning,这对于不可变类型来说再次变得更加理智。)

总而言之,设计人员选择在Java中创建字符串并且作为日常程序员可能有几个原因可以帮助你解决问题(就像创建新字符串一样,如StringBuilder)。

  

为什么等待,notify和notifyall应该在synchronized块内?

以下是关于该问题的一些信息:wait(), notify() and notifyAll() inside synchronized statement

基本上,线程“通知”或“等待”是没有意义的,除非它已经拥有对象的监视器。

一般而言,如果您不熟悉Java,您可能还想查看java.util.concurrent中与并发相关的一些较新的util:http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/package-summary.html。通常,您可以依赖这些类并避免手动编码同步,这是众所周知的困难且容易出错。