Java 不可变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

我读过很多关于线程安全的书。在我的多线程程序的某些部分中,我更喜欢尝试不变性。在得到错误的结果后,我注意到我的不可变对象不是线程安全的,尽管它是100%不可变的。如果我错了,请纠正我

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);