我有一个简单的代码,我希望用唯一的id生成对象。这是代码段
public class Test {
private static long counter = 0;
private long id;
private Test() {
// Don't worry about overflow
id = counter++;
}
// Will this method always Test Object with unique id?
public static Test getTest() {
return new Test();
}
public long getId() {
return id;
}
}
想知道多个线程是否调用了getTest方法,所有TestObjects都有唯一的id吗?
答案 0 :(得分:2)
它不是线程安全的,因为两个线程可以同时执行counter ++,你可以得到意想不到的结果。
你应该使用AtomicInteger:
public class Test {
private static AtomicLong counter = new AtomicLong(0);
private long id;
private Test() {
// Don't worry about overflow
id = counter.incrementAndGet();
}
// Will this method always Test Object with unique id?
public static Test getTest() {
return new Test();
}
public long getId() {
return id;
}
}
答案 1 :(得分:1)
不,生成唯一ID不是线程安全的。很可能会发生对象将收到非唯一ID。你可以使用AtomicInteger / AtomicLong在private static AtomicLong counter = (new AtomicLong())
的构造函数中使这个工作(即counter.getAndIncrement()
)然后Test
。
它不是线程安全的原因是每个处理器/内核都有自己的一组寄存器,如果没有同步,变量可能在不同的处理器/内核中具有不一致的副本。即使在单处理器系统上,抢先式多线程也会引入同样的问题。在非抢占式线程系统中不需要同步。
答案 2 :(得分:0)
如果要锁定类级变量,也可以在构造函数中使用synchronize块(不是实例变量,因为实例变量不需要同步。一次只能有一个线程创建对象) 。 所以你也可以尝试这个作为你的构造函数。
private Test() {
// Don't worry about overflow
synchronized(Test.class){
id = counter++;
}
}