java - 对多个对象的并发更新

时间:2017-01-26 14:00:11

标签: java multithreading

我是Java并发的新手,我有一个类保存数据(下面的示例代码中有两个),应该使用get(如Map)访问,但出于性能原因,内部存储在数组中的数据。 / p>

这在多线程环境中运行,有时必须更新此索引。

public class ConcurrencySampleCode {

    private static Object lock = new Object();

    private Map<String, Integer> map = ...
    private double[] array = ...

    public Double get(String id) {
        synchronized (lock) {
            Integer i = map.get(id);
            if (i == null) {
                return null;
            }
            return array[i];
        }
    }

    public void update() {
        Map<String, Integer> tmpMap = updateMap(...);
        double[] tmpArray = updateArray(...);
        synchronized (lock) { // should be atomic
            map = tmpMap;
            array = tmpArray;
        }
    }

}

我不确定这段代码是否正确?此外,get函数中是否需要synchronized关键字?

有更好的方法吗?

感谢您的帮助

2 个答案:

答案 0 :(得分:1)

您的代码没有任何问题,但您需要在地图和数组中使用volatile关键字,以确保所有线程立即看到更新的值,而我不是确定你想要锁是静态的。

作为替代方案,您可能需要查看java.util.concurrent.atomic包。它有一些方便的线程安全变量。例如,您可以将地图和数组移动到自己的类中,然后使用AtomicReference存储对象。

public class ConcurrencySampleCode {

    private AtomicReference<DoubleMap> atomicMap = new AtomicReference(new DoubleMap());

    //Inner class used to hold the map and array pair
    public class DoubleMap {
        private Map<String, Integer> map = ...
        private double[] array = ...
    }

    public Double get(String id) {
        DoubleMap map = atomicMap.get();
            ...
    }

    public void update() {
        Map<String, Integer> tmpMap = updateMap(...);
        double[] tmpArray = updateArray(...);
        DoubleMap newMap = new DoubleMap(tmpMap, tmpArray);
        atomicMap.set(newMap);
    }

}

答案 1 :(得分:0)

并发编程中有很多事情发生,但例如你的update()方法有问题。在当前状态下,多个Threads可以调用ConcurrencySampleCode.update(),并且每个人都会在同步开始之前在身体内发起update个调用。这意味着在循环周转之后更新调用的最后一个Thread将不会更新新更新的地图和数组中之前的update次调用。

长篇故事,尝试使用并理解ConcurrentHashMap