1

这个 Java 类是线程安全的吗?

class Counter() {

  private Long counter = 0;

  Long get() { return counter; }

  Long inc() { return ++counter; }
}

synchronized如果不是,是否可以在不显式使用锁(或关键字)的情况下使其成为线程安全的?如果不是,那么我猜以下是实现我的目标的最简单方法?

class Counter() {

  private final AtomicLong counter = new AtomicLong(0);

  Long get() { return counter.get(); }

  Long inc() { return counter.incrementAndGet(); }
}
4

3 回答 3

8

不,第一个示例不是线程安全的,因为++counter它不是原子的。例如,没有什么可以阻止两个线程++counter同时执行并丢失其中一个增量。

第二个示例线程安全的,这意味着不会丢失任何增量。值得注意的是,两者都get()返回inc()一个值,当调用者收到它时,它很可能已经过时了。

于 2013-03-18T13:47:19.780 回答
2

关于线程安全和多头的不同答案。Java 中的 long 是 64 位,占用两个单独的 32 位寄存器。你有高 32 位和低 32 位。一次写入占两个非原子 32 位存储。

您最终可能会从一个线程写入高 32 位,从另一个线程写入低 32 位,这可能会产生一个既不是来自第一个线程也不是来自第二个线程的数字。

于 2013-03-18T13:57:04.300 回答
0

Long是不可变的,那么它是线程安全的。不是线程安全的是 unbox-increment-and-assign 所需的inc,它(正确实现)相当于:

Long inc() { return counter= long.longValue()+1; }
于 2013-03-18T13:49:13.547 回答