4

注意::这个问题与内存可见性有关,而不是“公共”、“私人”等。

可以说我有以下课程:

public class Data {
    public final byte[] array;
    public final int offset, length;
    public Data(byte[] array, int offset, int length) {...}
    ...
}

(上述数组中的元素可以通过未显示的方法进行更改。)

现在假设我在另一个类中有一个包含给定数据的队列:

final ConcurrentLinkedQueue<Data> queue = new ConcurrentLinkedQueue<>();

现在假设我在带有队列的类中有以下代码:

Data data = queue.poll();
... code for reading the elements in the data object.

我的问题是:在轮询队列之前设置的数组中的元素是否保证对从队列中轮询数据的线程可见?

我知道队列轮询之后设置的元素对读者是不可见的,我只对队列轮询之前设置的元素感兴趣。

如果不是,我的理解是在调用 poll 方法之后放置的以下代码将确保数组的可见性

data = new Data(data.array, data.offset, data.length);

因为对象构造确保对象字段的完全可见性。它是否正确?

谢谢!

4

2 回答 2

4

文档说:

java.util.concurrent 及其子包中所有类的方法将这些保证扩展到更高级别的同步。尤其:

在将对象放入任何并发集合之前的线程中的操作发生在另一个线程中从集合中访问或删除该元素之后的操作。

所以是的,您可以保证看到在将对象存储到队列之前已设置的数组中的值。(我假设您在将 te 数组存储到此处的队列后不会修改一次)。

于 2013-02-03T20:39:58.993 回答
1

在对象构造之后,最终字段保证可见且正确。注意:这不会扩展到那些字段引用的对象。即 byte[] 可能不一致(但我怀疑它会在大多数 JVM 上)

有一个简单的解决方案是使用 ExecutorService。它不仅包装了一个队列和一个线程池,而且对 volatile 字段进行了足够的访问,以确保您的数据是正确的。

简而言之,保持简单,使用标准库,它更有可能工作。

于 2013-02-03T20:44:00.933 回答