是长线程安全吗?

时间:2013-03-18 13:45:31

标签: java concurrency thread-safety

这个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(); }
}

3 个答案:

答案 0 :(得分:8)

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

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

答案 1 :(得分:2)

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

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

答案 2 :(得分:0)

Long是不可变的,然后 是线程安全的。什么是非线程安全inc所需的unbox-increment-and-assign,(正确实施)相当于:

Long inc() { return counter= long.longValue()+1; }