首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >同步块是否触发数组的完整内存围栏?

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

Stack Overflow用户
提问于 2015-12-31 06:58:46
回答 1查看 405关注 0票数 5

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

这个问答很有帮助,但没有回答我所有的问题:, or synchronized suffices?

下面是演示问题的示例代码。假设有一个工作线程池,它通过方法SharedTable填充add(...)。在完成所有工作线程之后,最后一个线程读取并保存数据。

演示问题的示例代码:

代码语言:javascript
复制
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实现,它充当“易失性值/引用的数组”。

代码语言:javascript
复制
public final class SharedTable2 {

    // Column-oriented data entries
    private final AtomicReferenceArray<String> 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
        }
    }
}
  1. SharedTable线程安全(和缓存一致)吗?
  2. SharedTable (多吗?)效率更高,因为只需要一个内存围栏,而SharedTable2为每次调用Atomic*Array.set(...)调用一个内存围栏

如果有帮助,我将在64位x86硬件(Windows )上使用Java 8。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-12-31 07:16:00

不,SharedTable不是线程安全的.只有当您从同步块读取使用同一锁从同步块中写入的内容时,才能保证会发生这种情况。

由于写是由同步块组成的,所以JMM不能保证读取器线程可以看到写入。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34542492

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档