Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/310.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 是否需要同步读取列表而不修改列表的方法?_Java_Multithreading - Fatal编程技术网

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

Java 是否需要同步读取列表而不修改列表的方法?,java,multithreading,Java,Multithreading,我对合音还不熟悉。我知道,当我尝试使用多线程时,我可能会在向列表中添加内容时遇到问题。例如,使用以下代码: import java.util.ArrayList; class MySafeList extends ArrayList<Double>{ static ArrayList<Double> mySafeList; public boolean add(Double d){ mySafeList.add(d);

我对合音还不熟悉。我知道,当我尝试使用多线程时,我可能会在向列表中添加内容时遇到问题。例如,使用以下代码:

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

}
import java.util.ArrayList;
类MySafeList扩展了ArrayList{
静态数组列表mySafeList;
公共布尔加法(双d){
mySafeList.add(d);
返回true;
}
公共整数大小(){
返回mySafeList.size();
}
公共双获取(int i){
返回我的安全列表。获取(i);
}
静态布尔测试(int n,int m){
螺纹[]=新螺纹[n];
试一试{

对于(int i=0;i如果有代码可以在其他线程读取列表时修改列表,那么是的,您需要同步-以便在读取列表时不会修改列表

最简单的方法是将“synchronized”添加到“add”、“get”和“size”方法中

有人可能会质疑是否需要在“大小”上使用它,但我认为在这种情况下省略同步可能不会有什么好处,至少正如您在这里所写的那样


一个不相关的问题:为什么您的“add”调用返回一个硬连线的“true”值(使返回无效),而不是列表“add”中的值?如果您不需要知道某个项是否已实际添加,请将其设为void方法。

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


这是一个比我更好的答案,除非你的目的是通过自己编码来理解基本机制。因此,在将同步原语添加到
add()
方法后,不必在不修改列表的情况下同步读取列表的方法(
size()
get()
)?如果您使用的是synchronizedList,则不需要同步任何add、size、get,因为synchronizedList是为您而做的。事实上,似乎不需要您的整个类MySafeList:只需使用synchronizedList即可。但这是否需要取决于您编写此代码的目的。这是不正确的。您需要同步,句号。“在其他线程读取时修改列表”不是全部。问题是可见性。写入(或其他操作)除非读和写都是同步的,否则不能保证在Java的内存模型中是可见的,而且它们必须在同一个锁/监视器上同步。请参考关于这个主题的其他文章,并在实践中获得Brian Goetz的Java并发性的副本,这确实是关于Java多线程的最好的书。我想这在一开始是正确的方法。但是在阅读@markspace comment之后,我感到困惑。其次,我的'add'调用返回一个硬连接的'true',只要我有错误,如果我没有。我将再次检查。哦,对了。您的代码扩展了ArrayList,所以您希望保留'add'的语义和签名。但是硬连接是真的不正确;您应该返回基础“add”调用的结果。类结构似乎很奇怪。您的类扩展了ArrayList,但存在一个静态ArrayList。这意味着在执行
MySafeList x=new MySafeList()之后
ArrayList有两个实例,其中一个大部分未使用,除了所有未重写的方法。这会让人感到困惑,例如size()可能返回非零,但isEmpty()将说是真的,因为您没有覆盖它..然后,如果您也执行
MySafeList y=new MySafeList();//第二个列表
,有时x和y是相同的列表(添加到x的内容显示在y中,反之亦然),有时则不是(任何您没有覆盖的ArrayList方法)。
List<Double> mySafeList = Collections.synchronizedList(new ArrayList<>());
List<Double> mySafeList = new CopyOnWriteArrayList<>();