首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >并发从/写入int数组的快速读取/写入

并发从/写入int数组的快速读取/写入
EN

Stack Overflow用户
提问于 2014-01-21 01:05:57
回答 3查看 1.4K关注 0票数 3

我需要一种快速的方式来同时读取/写入int数组。每个索引都需要写入。在完成所有写操作之后,只需要对整个数组执行读取操作。

我从一个同步版本开始:

代码语言:javascript
复制
public final class SynchronizedIntArray {
    private final int[] elements = new int[1000000];

    public synchronized void set(int index, int value)
    {
        elements[index] = value;
    }

    public synchronized int[] getAll()
    {
        return elements;
    }
}

表演不太好。我在网上寻找了更好的解决方案,并找到了AtomicIntegerArray。

代码语言:javascript
复制
public final class ConcurrentIntArray
{
    private final AtomicIntegerArray elements = new AtomicIntegerArray(1000000);

    public void set(int index, int value)
    {
        elements.set(index, value);
    }

    public int[] getAll()
    {
        int[] intArray = new int[elements.length()];
        for (int i = 0; i < intArray.length(); i++) {
            intArray[i] = elements.get(i);
        }
        return intArray;
    }
}

但是,我想知道为什么没有方法一次从AtomicIntegerArray获得完整的int数组。性能仍然比同步版本好得多,但我真的需要以这种方式复制吗?

对于我的问题,还有比AtomicIntegerArray更快的替代方案吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-01-21 01:14:04

是的,你真的需要用这种方式复制它。AtomicIntegerArray的实现意味着在没有任何其他线程同时进行更改的情况下,无法锁定整个数组并获得它:您一次只能获得一个元素。

票数 4
EN

Stack Overflow用户

发布于 2014-01-23 03:37:26

我不是Java程序员,但作为一个实时程序员,我认为您的两个实现在概念上都是错误的。

不过,我可能误解了Java同步的工作方式。在这种情况下,请不要理会这篇文章,接受我的道歉。

你的第一个解决方案

确保写入器之间没有并发性,因为您锁定了对唯一允许修改一个元素的函数的访问。

您还可以将对数组的访问锁定为一个整体,但只能在读取器之间进行(这是无用的,因为读取器不会修改数据,因此可以安全地同时读取数组)。

但是,您并不阻止读者和作者之间的并发访问。有可能一个(单个)读取器读取由(单个)编写器修改的元素的值。

此外,您将返回对成员数组的引用,而不是副本,因此调用方将访问可能在任何时候被写入者覆盖的实际数据。

因此,即使在调用读访问器之后,在写过程中也根本没有保护数组不受读访问的影响。

如果由于某种原因,对数组元素的实际访问是原子的(我非常怀疑,但Java不是我的首选),或者更有可能是因为潜在的不一致是罕见的,而且不易检测,那么代码可能会工作。如果您在不同的环境上运行,或者甚至稍微更改代码,您的应用程序可能会陷入混乱,从而增加并发读/写的发生,或者变得更容易受到这些不一致的影响。

你的第二个解决方案

使用与前面代码相同的AtomicArray,但在单个数组值上为并发读取添加保护。

它消除了第一种解决方案的潜在不一致性(这也是因为这一次您的读取器函数被迫返回实际数组的副本),但是读取整个数组的效率非常低,因为您的AtomicArray对象将获取并释放每次读取的值的锁。

可能的办法

您必须保护的是整个数组。

在一般情况下,您可能需要使用读取器/写入器锁。这将允许多个读取器同时访问该数组。

但是,如果我正确理解,在您的情况下只有一个读取器,所以最好使用一个简单的锁。

您的单次写入和全局读取的代码如下:

代码语言:javascript
复制
public final class SynchronizedIntArray {
    private final int[] elements = new int[1000000];
    private final Lock lock = new ReentrantLock();

    public void set(int index, int value)
    {
        lock.lock();
        elements[index] = value;
        lock.unlock();
    }

    public int[] getAll()
    {
        int[] copy;
        lock.lock();
        copy = elements.clone();
        lock.unlock();
        return copy;
    }
}
票数 1
EN

Stack Overflow用户

发布于 2014-01-22 23:36:32

是的,对于用例来说,有一个比AtomicIntegerArray更好的实现。这里的关键是引用,而int赋值是原子的。易失性写入没有由编译器优化。

代码语言:javascript
复制
//This class is thread safe 
public final class BetterIntArray {

private volatile int[] elements = new int[1000000]; // Don't make it finall

public void set(int index, int value)
{
    elements[index] = value; //assignment is atomic
    elements =  elements; // guarantees that changes are visible to other thread
}

public int[] getAll()
{
    return elements ;
}    

}

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

https://stackoverflow.com/questions/21247283

复制
相关文章

相似问题

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