在多线程环境中以下列方式构造对象是否安全 问问题

public class DataEvent {

    private static final AtomicInteger lastRevision = new AtomicInteger();

    private final int revision;

    private final long threadId;

    private final long timestamp;


    private DataEvent(int revision) {

        this.revision = revision;

        this.threadId = Thread.currentThread().getId();

        this.timestamp = System.nanoTime();

    }


    public static DataEvent newInstance() {

        return new DataEvent(lastRevision.incrementAndGet());

    }

}

My questions are following:

  • is it absolutely correct to say that all objects will be constructed consistently one by one? I mean that every new object is constructed later then previous one. In other words each new object has that is bigger then previous one.timestamp

  • how keyword affects this behavior? As I understand if all object fields are then it makes constructor atomic in some way. Reference is not published until all fields are initialized.finalfinalfinal

  • what is best practice to construct such objects? Is is enough to make atomic or should be declared as ?lastRevisionnewInstancesynchronized



元芳怎么了
浏览 124回答 2
2回答

冉冉说

说所有对象都将一个接一个地一致地构造是绝对正确的吗?哈哈 是阻塞调用,但调度程序可以在收到第一个 ID 后暂停第一个线程,然后在第二个线程收到第二个 ID 后恢复它,这意味着两个构造函数将同时执行。lastRevision.incrementAndGet()换句话说,每个新对象的时间戳都比前一个对象大。不,见上文。关键字如何影响此行为?final事实并非如此。据我所知,如果所有对象字段都是最终的,那么它就会以某种方式使构造函数成为原子的。不對。如果每个字段都是最终的,那么一个类是不可变的*,这使得它隐式线程安全。构造此类对象的最佳实践是什么?是否足以使原子化或应声明为同步?lastRevisionnewInstance如果必须按顺序创建每个实例,则应进行同步。一旦是,原子整数就没有意义了。即使这样做,时间戳可能仍然相同,具体取决于基础系统时钟的分辨率。newInstance*嗯,不完全是。如果每个字段都是最终的,并且本身也是不可变的。

心有法竹

原子性保证仅对调用有效。所以,是的,对于每个新对象,修订将是连续的,这是原子数据类型的目的。因此,为了回答您的问题:不能保证多个线程将按照调用 时相同的顺序执行构造函数中的语句。要实现此目的,您必须将此部分放在块中。incrementAndGet()incrementAndGet()synchronizedfinals在这里没有帮助。它们是纯粹的逻辑功能,不允许在对象创建后改变字段。如果您确实需要时间戳与修订对齐,则必须引入某种形式的线程同步。您可以使整个方法同步,然后不必是原子的。lastRevision此外,无论您决定做什么,您可能还需要检查其自身提供的保证。咔嚓System.nanoTime()
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java