关于java:byte数组在多线程中读写

byte array read and write in multithreads

我为线程分配了一个非常大的字节数组,以读取和写入数组中的字节。写入操作是将新字节直接分配给数组中的值,例如byte[i] = byte2;

我可以确保这些操作不会发生冲突(字节数组中的同一部分将不会由2个不同的线程进行写入。读取部分时,其他线程将不会执行任何写入操作)。我担心的是对数组的修改是否可立即用于其他线程。我知道可能存在内存隔离,哪些其他线程可能仍会读取数组中的旧值。

如果存在问题,如何避免? volatile byte[] store;在这种情况下可以工作吗?


will the modification to array been instantly available to other threads.

并非没有写者的写保护区和读者的读保护区。

I know there might be memory fence, which other threads may still read the old values in the array.

您将需要为读取器和写入器使用其中之一(不是每个字节一个,每个操作一个)

will volatile byte[] store; works in this circumstance?

它不会执行您想要的操作,尽管它会减慢您的应用程序的速度。当你做

1
store[i] = b;

当您正在读取对字节[]的store引用时,这增加了一个读取篱笆。

最好的解决方案是使用Unsafe完全控制这些读写操作。请参阅AtomicIntegerArray的代码。

但是,如果不走这条路,您可以执行这样的虚拟操作,虽然效率不高,但实现起来却简单得多。

1
2
3
4
5
6
7
8
9
private final AtomicBoolean fence = new AtomicBoolean();

public void readFence() {
    fence.get();
}

public void writeFence() {
    fence.set(true);
}

要使其正常工作,必须在所有写入之后执行writeFence(),并在所有读取之前执行readFence()

如果您走的是更底层的路由,则可能会发现使用堆外内存是一个优势。堆外内存可以存储大量(TB)的数据,而不会影响GC。


您可以为此使用SynchronizedList
例子

1
2
byte[] c = new byte[];
List list = Collections.synchronizedList(Arrays.asList(c));

它将是线程安全的