Java 不可变100%,但仍然不是线程安全的
我读过很多关于线程安全的书。在我的多线程程序的某些部分中,我更喜欢尝试不变性。在得到错误的结果后,我注意到我的不可变对象不是线程安全的,尽管它是100%不可变的。如果我错了,请纠正我Java 不可变100%,但仍然不是线程安全的,java,multithreading,thread-safety,immutability,Java,Multithreading,Thread Safety,Immutability,我读过很多关于线程安全的书。在我的多线程程序的某些部分中,我更喜欢尝试不变性。在得到错误的结果后,我注意到我的不可变对象不是线程安全的,尽管它是100%不可变的。如果我错了,请纠正我 public final class ImmutableGaugeV4 { private final long max, current; public ImmutableGaugeV4(final long max) { this(max, 0); } private ImmutableGaugeV
public final class ImmutableGaugeV4 {
private final long max, current;
public ImmutableGaugeV4(final long max) {
this(max, 0);
}
private ImmutableGaugeV4(final long max, final long current) {
this.max = max;
this.current = current;
}
public final ImmutableGaugeV4 increase(final long increament) {
final long c = current;
return new ImmutableGaugeV4(max, c + increament);
}
public final long getCurrent() {
return current;
}
public final long getPerc() {
return current * 100 / max;
}
@Override
public final String toString() {
return "ImmutableGaugeV4 [max=" + max + ", current=" + current + "](" + getPerc() + "%)";
}
}
AAAA
这个不可变对象有什么问题?在不使用内部锁的情况下实现线程安全缺少什么?您的问题是,您没有对数值变量max和current使用线程安全操作。因此,许多线程可以从它们那里获得相同的值,即使它已经被更改了 您可以添加同步块来处理对它们的读/写操作,但最好的方法是使用线程安全类来处理 如果你需要长值,那就是原子长。看看它的文档,它有一些方法来完成您想要的操作 无论何时进行多线程处理,都应该使用线程安全对象,例如原子族、ConcurrentHashMap for maps等等 希望有帮助 都不是
final long c = current;
return new ImmutableGaugeV4(max, c + increament);
也不是
是线程安全的。这些复合动作不是原子的
我建议阅读Brian Goetz的“Java并发实践”:专门讨论复合操作和“发布和转义”问题的章节。您的类
T4
并不是一成不变的。这就是你通过重新分配g3而改变的。你的问题是什么??生成4个不同的不可变对象。这与线程安全无关。我很惊讶竟然有人对此投了更高的票
ImmutableGaugeV4 [max=10000, current=9994](99%)
ImmutableGaugeV4 [max=10000, current=9995](99%)
ImmutableGaugeV4 [max=10000, current=9996](99%)
ImmutableGaugeV4 [max=10000, current=9997](99%)
final long c = current;
return new ImmutableGaugeV4(max, c + increament);
g3 = g3.increase(1);