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