有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

多线程是java中唯一id的线程安全代码

我有一个简单的代码,希望生成具有唯一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方法所有testobject都有唯一的id吗


共 (3) 个答案

  1. # 1 楼答案

    如果要锁定类级变量(不是实例变量,因为实例变量不需要同步。一次只能有一个线程创建对象),也可以在构造函数中使用synchronize block。 所以你也可以把它作为构造器来尝试

    private Test() {
        // Don't worry about overflow
        synchronized(Test.class){
        id = counter++;
        }
    }
    
  2. # 2 楼答案

    不,生成唯一ID不是线程安全的。对象很可能会收到非唯一ID。可以使用AtomicInteger/AtomicLong来实现这一点(即private static AtomicLong counter = (new AtomicLong())),然后在Test的构造函数中counter.getAndIncrement()

    它不是线程安全的原因是每个处理器/内核都有自己的寄存器集,如果不同步,变量在不同的处理器/内核中可能有不一致的副本。即使在单处理器系统上,抢占式多线程也会带来同样的问题。在非抢占式线程系统中不需要同步

  3. # 3 楼答案

    这不是线程安全的,因为两个线程可以同时执行计数器+,并且可能会得到意外的结果

    您应该使用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;
        }
    }