Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/363.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 同时快速读取/写入int数组_Java_Concurrency - Fatal编程技术网

Java 同时快速读取/写入int数组

Java 同时快速读取/写入int数组,java,concurrency,Java,Concurrency,我需要一种快速的方法来并发地读/写int数组。 每个索引都需要写入。读取操作仅适用于以下情况: 完成所有写入操作后完成数组 我从一个同步版本开始: public final class SynchronizedIntArray { private final int[] elements = new int[1000000]; public synchronized void set(int index, int value) { elements[in

我需要一种快速的方法来并发地读/写int数组。 每个索引都需要写入。读取操作仅适用于以下情况: 完成所有写入操作后完成数组

我从一个同步版本开始:

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

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;
    }
}
public final class ConcurrentIntArray
{
私有最终AtomicIntegerArray元素=新的AtomicIntegerArray(1000000);
公共无效集(int索引,int值)
{
元素集(索引、值);
}
public int[]getAll()
{
int[]intArray=newint[elements.length()];
对于(int i=0;i
但是我想知道为什么没有方法从中获取完整的int数组 原子的整体性立刻消失了。 性能仍然比同步版本好得多,但是 我真的需要用这种方式复制它吗


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

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

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

//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 ;
}    

}我不是Java程序员,但作为一名实时程序员,我认为您的两种实现在概念上都是错误的。
不过,我可能误解了Java同步的工作原理。在这种情况下,请忽略此帖子并接受我的道歉

您的第一个解决方案 确保写入程序之间没有并发,因为您锁定了对唯一允许修改一个元素的函数的访问。
您还可以将对阵列的访问作为一个整体锁定,但只能在读卡器之间锁定(这是无用的,因为读卡器不会修改数据,因此可以同时安全地读取阵列)

但是,您不阻止读写器之间的并发访问。一个(单个)读卡器可能读取一个(单个)写卡器正在修改的元素的值

此外,您将返回对成员数组的引用而不是副本,因此调用方将访问可能随时被写入方覆盖的实际数据。
因此,即使在调用读访问器之后,阵列在写入期间也不会受到读访问的保护

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

你的第二个解决方案 使用AtomicArray,其作用与之前的代码相同,但为单个数组值上的并发读取添加了保护
它消除了第一个解决方案的潜在不一致性(也因为这一次您的reader函数被迫返回实际数组的副本),但是读取整个数组的效率非常低,因为您的AtomicArray对象将获取并释放每次读取值的锁

可能的办法 您必须保护的是整个阵列

在一般情况下,您可能需要使用读写器锁。这将允许多个读卡器同时访问阵列。
然而,如果我理解正确,在您的情况下只有一个读卡器,所以最好使用一个简单的锁

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

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;
    }
}

你说“性能不好”-哪里不好。我不认为你会比
元素[index]=value更好
查看
AtomicIntegerArray
的代码,看看他们在做什么。@user2310289实际上,根据,他们正在使用sun.misc.Unsafe类将存储外包给本机方法,这取决于实现的速度,可能更快,也可能更快…@user2310289:性能优势不在于数组分配,而在于避免
同步
,它为单个赋值锁定整个数组。谢谢-我应该接受我自己的建议。请务必提及向下voting的原因数组
元素[index]
的赋值不是真正的原子(易变的)。只有
元素
变量本身的赋值是可变的。参见,例如。,