我正在尝试计算在多线程环境下进程运行时生成的类的实例数。我这样做的方法是通过查看这篇文章来增加构造函数中的静态计数器: How to Count Number of Instances of a Class
因此,在多线程环境中,以下是我定义类的方法:
class Television {
private static volatile int counter = 0;
public Television(){
counter ++;
}
}
但是,我不确定上面的代码是否存在潜在的错误,因为我认为java中的构造函数并不意味着同步而counter++
不是原子的所以如果两个线程同时创建实例,那么代码是不是一个错误?但我还不太确定。
答案 0 :(得分:3)
此代码中存在错误(特别是竞争条件),因为计数器的读取和写入计数器不是以原子方式执行的。
换句话说,两个线程可以读取counter
的相同值,递增该值,然后将相同的值写回变量。
Thread 1 Thread 2
======== ========
Read 0
Read 0
Increment
Increment
Write 1
Write 1
之后,该值将为1,而不是2。
改为使用AtomicInteger
和AtomicInteger.incrementAndGet()
。
答案 1 :(得分:1)
由于counter++
不是原子的,你可以将它替换为线程安全的JDK AtomicInteger
。
您可AtomicInteger
使用getAndIncrement()
方法,如下所示:
class Television {
private static final AtomicInteger counter = new AtomicInteger();
public Television(){
counter.getAndIncrement();
}
}
AtomicInteger用于原子等应用程序 增量计数器,不能用作替代 整数。
您可以查看here
答案 2 :(得分:1)
这里有两种方法绕过底层" ++ on int"不是原子操作:
A)正如其他人所建议的那样,使用AtomicInteger
B)引入一个普通的LOCK,所有ctors都可以用来同步;像:
private final static Object LOCK = new Object();
public Television() {
synchronized (LOCK) {
counter++;
}