AtomicReference到可变对象和可见性

Jan*_*sch 8 java concurrency multithreading mutable atomicreference

假设我有一个AtomicReference对象列表:

AtomicReference<List<?>> batch = new AtomicReference<List<Object>>(new ArrayList<Object>());
Run Code Online (Sandbox Code Playgroud)

线程A将元素添加到此列表:batch.get().add(o);

稍后,线程B获取列表,例如,将其存储在DB中:insertBatch(batch.get());

在写入(线程A)和读取(线程B)时,是否必须执行其他同步以确保线程B按照A离开的方式查看列表,或者由AtomicReference处理?

换句话说:如果我有一个可变对象的AtomicReference,并且一个线程更改了该对象,其他线程是否会立即看到此更改?

编辑:

也许一些示例代码是有序的:

public void process(Reader in) throws IOException {
    List<Future<AtomicReference<List<Object>>>> tasks = new ArrayList<Future<AtomicReference<List<Object>>>>();
    ExecutorService exec = Executors.newFixedThreadPool(4);

    for (int i = 0; i < 4; ++i) {
        tasks.add(exec.submit(new Callable<AtomicReference<List<Object>>>() {
            @Override public AtomicReference<List<Object>> call() throws IOException {

                final AtomicReference<List<Object>> batch = new AtomicReference<List<Object>>(new ArrayList<Object>(batchSize));

                Processor.this.parser.parse(in, new Parser.Handler() {
                    @Override public void onNewObject(Object event) {
                            batch.get().add(event);

                            if (batch.get().size() >= batchSize) {
                                dao.insertBatch(batch.getAndSet(new ArrayList<Object>(batchSize)));
                            }
                    }
                });

                return batch;
            }
        }));
    }

    List<Object> remainingBatches = new ArrayList<Object>();

    for (Future<AtomicReference<List<Object>>> task : tasks) {
        try {
            AtomicReference<List<Object>> remainingBatch = task.get();
            remainingBatches.addAll(remainingBatch.get());
        } catch (ExecutionException e) {
            Throwable cause = e.getCause();

            if (cause instanceof IOException) {
                throw (IOException)cause;
            }

            throw (RuntimeException)cause;
        }
    }

    // these haven't been flushed yet by the worker threads
    if (!remainingBatches.isEmpty()) {
        dao.insertBatch(remainingBatches);
    }
}
Run Code Online (Sandbox Code Playgroud)

这里发生的是我创建了四个工作线程来解析一些文本(这是方法的Reader in参数process()).每个工作程序保存它在批处理中解析的行,并在批处理完成时刷新批处理(dao.insertBatch(batch.getAndSet(new ArrayList<Object>(batchSize)));).

由于文本中的行数不是批处理大小的倍数,因此最后一个对象最终会在未刷新的批处理中结束,因为它未满.因此,这些剩余的批次由主线程插入.

我用AtomicReference.getAndSet()一个空的替换整批.这个程序在线程方面是否正确?

Tud*_*dor 10

嗯......它真的不像这样.AtomicReference保证引用本身在线程中可见,即如果为其分配的引用与原始引用不同,则更新将是可见的.它不保证引用所指向的对象的实际内容.

因此,对列表内容的读/写操作需要单独同步.

编辑:因此,根据您更新的代码和您发布的评论判断,设置本地引用volatile足以确保可见性.