是否需要同步读取列表而不修改列表的方法?

时间:2019-04-24 23:57:08

标签: java multithreading

我是同步化的新手。我知道当我尝试使用多线程时,在将内容添加到列表中时可能会遇到问题。例如,使用以下代码:

import java.util.ArrayList;

class MySafeList extends ArrayList<Double>{

    static ArrayList<Double> mySafeList;

    public boolean add(Double d){
        mySafeList.add(d);
        return true;
    }

    public int size(){
        return mySafeList.size();
    }

    public Double get(int i){
        return mySafeList.get(i);

    }

    static boolean stressTest(int n, int m){
        Thread threads[] = new Thread[n]; 
        try{
            for(int i=0; i<n; i++){
                threads[i] = new Thread(new ThreadTest(1));
                threads[i].start();
                for(int j=0; j<m;j++){
                    Double d = new Double((double) j);
                    mySafeList.add(d);
                }
            }
            return true;
        }catch(Exception e){
            return false;
        }
    }

    public static void main(String[] args) {
        MySafeList safeList = new MySafeList();
        stressTest(2,4);    
    }

}

我想将同步原语添加到add ()方法中,是否需要同步读取列表而不修改列表的方法(size ()get ())? 如有必要,如何同步这些原语并验证MySafeList是否可用于nm的任何值?

2 个答案:

答案 0 :(得分:2)

如果要同步列表,请使用synchronizedList

List<Double> mySafeList = Collections.synchronizedList(new ArrayList<>());

请注意,迭代不会同步。


或者,如果您想要不同步的读取访问,但以降低写入速度为代价,请使用CopyOnWriteArrayList

List<Double> mySafeList = new CopyOnWriteArrayList<>();

答案 1 :(得分:1)

如果在其他线程正在读取列表时有代码可以修改列表,那么是的,您需要进行同步-以便在读取列表时不会对其进行修改。

最简单的方法是将“已同步”添加到“添加”,“获取”和“大小”方法中。

人们可能会质疑“大小”是否需要,但是我认为,在这种情况下,至少在您在此处编写时,忽略同步几乎不会带来任何好处。

一个不相关的观点:为什么您的“添加”调用返回一个硬连接的“真实”值(使返回无效)而不是列表中“添加”的值?如果您不需要知道是否实际添加了项目,则将其设为void方法。