是否需要在Java中同步对字符串的只读访问权限?
答案 0 :(得分:10)
String
等不可变对象是线程安全的,因为它们的内部状态永远不会改变,final
对这些String
对象的引用是线程安全的。
但是,如果您对不可变对象有非最终引用,它不是完全线程安全的。
鉴于:
public final String x = "This reference is thread safe, it can never change";
对x
的任何引用都是线程安全的,因为x
引用的内容永远不会更改且String
对象不可变。
并给出:
public String s = "This reference is not thread safe, it can change";
对s
的任何引用都不线程安全,因为s
可能会更改为其他内容。那就是:
s = "this is another different immutable String";
可以更改s
引用的内容。如果您的引用永远不会更改,请将它们final
设置为volatile
,您应该声明它们s
,以便JVM知道重新读取引用的内容而不执行任何可能错过的缓存验证更改为public volatile String s = "This reference is expected to change, so tell the JVM";
。
final
有关线程安全和{{1}}关键字的详细信息,请参阅The final word on final。
答案 1 :(得分:5)
没有。字符串是不可变的。如果你所做的只是阅读字符串,那你就没事了。
编辑添加:是的,如果您有可变属性,则需要同步更改属性的值。
答案 2 :(得分:4)
本身不是String
,而是String
的引用。
编辑:
并不保证所有线程都能看到未声明为final(或以其他方式同步)的变量引用。虽然许多线程可以安全地读取相同String
对象的值,但您需要以某种方式保证所有线程都在读取最新的参考。
答案 3 :(得分:2)
字符串是不可变对象,因此它们本身就是线程安全的。请注意,像String.toUpperCase()这样的函数不会更改String对象本身,但会返回一个新的String。
StringBuffer和StringBuilder是可变对象。 StringBuffer是线程安全的,StringBuilder不是。
答案 4 :(得分:1)
每个String访问都是只读(字符串是不可变的),并且因为String
实例的内容无法更改,所以不需要同步。