当前位置:  开发笔记 > 编程语言 > 正文

同步块是否会触发数组的完整内存栅栏?

如何解决《同步块是否会触发数组的完整内存栅栏?》经验,为你挑选了0个好方法。

我对在Java中的线程之间安全地共享数组感到困惑,特别是内存栅栏和关键字synchronized.

这个Q&A很有帮助,但没有回答我的所有问题:Java数组:synchronized + Atomic*,还是同步的?

以下是演示该问题的示例代码.假设有一个工作线程池填充了SharedTablevia方法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 AtomicReferenceArray data1Arr;
    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.

推荐阅读
Chloemw
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有