Java 不可变对象上的线程安全
我在读java中的不可变对象 有一条语句声明:“不可变对象是线程安全的”。 我需要对上述声明进行更多澄清: 如果我有一个“String”类型的共享资源,它与多个线程共享(比如3个线程) 如果其中一个线程对共享引用进行了更改,它将创建一个新的字符串对象,该对象将仅对该线程对象可用,而其他线程将无法了解其中一个线程所做的更改 这不会导致数据不一致吗 有人能帮我理解吗Java 不可变对象上的线程安全,java,string,immutability,Java,String,Immutability,我在读java中的不可变对象 有一条语句声明:“不可变对象是线程安全的”。 我需要对上述声明进行更多澄清: 如果我有一个“String”类型的共享资源,它与多个线程共享(比如3个线程) 如果其中一个线程对共享引用进行了更改,它将创建一个新的字符串对象,该对象将仅对该线程对象可用,而其他线程将无法了解其中一个线程所做的更改 这不会导致数据不一致吗 有人能帮我理解吗 提前感谢。不可变类的对象始终是线程安全的。但是,对这样一个对象的引用与此无关。它可能是线程安全的,也可能不是线程安全的,这取决于包含对
提前感谢。不可变类的对象始终是线程安全的。但是,对这样一个对象的引用与此无关。它可能是线程安全的,也可能不是线程安全的,这取决于包含对此线程安全对象(例如,字符串对象)的引用的类以及操作此类引用的方法 请参见下面的示例,以说明说明:
public class User {
private string name;
public User(String name) {
this.name=name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name=name;
}
}
因此,即使String是一个不可变且线程安全的类,上面的类User中对它的引用也不是线程安全的,因为它的方法可以同时将该引用更改为新的String对象
如果您希望它是线程安全的,那么有很多选择。其中之一是将所有可以更改名称对象的方法设置为synchronized不可变类型(在任何语言中)是特殊的引用类型。
它们的独特性在于,当它们被更改时,它们会被一个全新的实例替换,该实例反映了以前的状态+更改
假设两个线程运行一个函数,该函数接收一个不可变的引用类型对象作为参数(当然,本例中我将使用string)
//伪代码
main()
{
var str = "initialState";
new Thread(Do,str,1).Start();
new Thread(Do,str,2).Start();
}
void Do(string arg,int tid)
{
int i = 0;
while(true)
{
arg += "running in thread " + tid + "for the " + i + "time";
Console.WriteLine(arg);
}
}
该程序在并行打印时,在不影响其他线程中打印内容的情况下,在每个线程中运行的事件数
为什么?
如果您认为string是一种引用类型,那么它是通过引用而不是通过值传递的,这意味着它不是复制的,只有引用的副本才会发生。
尽管它最初是同一个物体。在第一次更改之后,它将不再存在,并创建一个不同的更改。
如果更改后它仍然是同一个对象,则它将是两个线程之间的共享资源,并将破坏这些线程无法打印的状态。如果存在可以“更改”的“共享引用”,则不是该对象不是线程安全的,而是该引用可能不安全。这并不意味着物体不安全。