我对在Java中的线程之间安全地共享数组感到困惑,特别是内存栅栏和关键字synchronized
.
这个Q&A很有帮助,但没有回答我的所有问题:Java数组:synchronized + Atomic*,还是同步的?
以下是演示该问题的示例代码.假设有一个工作线程池填充了SharedTable
via方法add(...)
.完成所有工作线程后,最后一个线程将读取并保存数据.
用于演示此问题的示例代码:
public final class SharedTable { // Column-oriented data entries private final String[] data1Arr; private final int[] data2Arr; private final long[] data3Arr; private final AtomicInteger nextIndex; public SharedTable(int size) { this.data1Arr = new String[size]; this.data2Arr = new int[size]; this.data3Arr = new long[size]; this.nextIndex = new AtomicInteger(0); } // Thread-safe: Called by worker threads public void addEntry(String data1, int data2, long data3) { final int index = nextIndex.getAndIncrement(); data1Arr[index] = data1; data2Arr[index] = data2; data3Arr[index] = data3; } // Not thread-safe: Called by clean-up/joiner/collator thread... // after worker threads are complete public void save() { // Does this induce a full memory fence to ensure thread-safe reading of synchronized (this) { final int usedSide = nextIndex.get(); for (int i = 0; i < usedSide; ++i) { final String data1 = data1Arr[i]; final int data2 = data2Arr[i]; final long data3 = data3Arr[i]; // TODO: Save data here } } } }
上面的示例代码也可以使用Atomic*Array
,它充当"易失性值/引用数组".
public final class SharedTable2 { // Column-oriented data entries private final AtomicReferenceArraydata1Arr; private final AtomicIntegerArray data2Arr; private final AtomicLongArray data3Arr; private final AtomicInteger nextIndex; public SharedTable2(int size) { ... } // Thread-safe: Called by worker threads public void addEntry(String data1, int data2, long data3) { final int index = nextIndex.getAndIncrement(); data1Arr.set(index, data1); ... } // Not thread-safe: Called by clean-up/joiner/collator thread... // after worker threads are complete public void save() { final int usedSide = nextIndex.get(); for (int i = 0; i < usedSide; ++i) { final String data1 = data1Arr.get(i); final int data2 = data2Arr.get(i); final long data3 = data3Arr.get(i); // TODO: Save data here } } }
是SharedTable
线程安全的(和缓存相干)?
是SharedTable
(更多?)更高效,因为只需要一个内存栅栏,而SharedTable2
每次调用都会调用内存栅栏Atomic*Array.set(...)
?
如果它有帮助,我在64位x86硬件(Windows和Linux)上使用Java 8.