我有点不了解不可变对象(immutable对象)。我的想法是它们在多线程环境中很有用,而且根据定义是线程安全的。
但下面的代码似乎恰恰相反!
public class ImmutableTest {
volatile ImmutableObject obj;
public static void main(String[] args) throws InterruptedException {
new ImmutableTest().execute();
}
private void execute() throws InterruptedException
{
obj = new ImmutableObject(0);
ExecutorService exec = Executors.newFixedThreadPool(50);
for(int i = 0; i < 50; i++){
exec.execute(new ImmutableRunnable(this));
}
Thread.sleep(5000);
exec.shutdown();
obj.print();
}
}
public class ImmutableRunnable implements Runnable {
ImmutableTest test;
ImmutableRunnable(ImmutableTest immutableTest) {
this.test = immutableTest;
}
public void run() {
this.test.obj = new ImmutableObject(this.test.obj.getValue());
}
}
public final class ImmutableObject {
private int n;
public ImmutableObject(int newValue) {
this.n = newValue;
if(Math.random() > .5){
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void print() {
System.out.println(n);
}
public int getValue() {
return n;
}
}
在线程安全环境中,我预计结果为 50。但这种情况并非如此。如果从 ImmutableObject 构造函数中取消随机 sleep ,您将获得 50。
那么结论是什么? “如果构造函数足够快”,不可变对象(immutable对象)是线程安全的吗?或者(更有可能)我误解了什么?
抱歉,我没有正确解释我的疑问。这不是同步问题,我学习了如何同步方法和使用锁。这个问题涉及不可变对象(immutable对象)及其与多线程的关系。我到处都读到不可变对象(immutable对象)是线程安全的,因此它可以在线程之间无所畏惧地共享。但恕我直言,这根本不是真的!!! 那么你能给我一个不可变对象(immutable对象)在不同线程之间共享并且它的使用不需要同步的例子吗? 谢谢大家。
最佳答案
你误会了什么。
不可变对象(immutable对象)让您可以安全地共享对象并读取任何方法/字段,无需使用锁。
在这种情况下,您依赖于 mutable obj
引用以某种方式进行同步 - 事实并非如此。
不变性只是一个无法修改的对象。修改状态后,您需要执行一些同步以确保实际发生您想要的。例如,整个“通过读取 obj 设置 obj”调用需要是互斥的,并且以串行方式发生。
关于用于多线程系统的 Java 不可变对象(immutable对象)。我做错了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12632428/