java - Collections.synchronizedList() 方法有什么用?它似乎没有同步列表

标签 java multithreading collections synchronization

我正在尝试使用两个线程将 String 值添加到 ArrayList。我想要的是,当一个线程添加值时,另一个线程不应该干扰,所以我使用了 Collections.synchronizedList 方法。但似乎如果我没有在对象上显式同步,则添加是以非同步方式完成的。

没有显式同步块(synchronized block):

public class SynTest {
    public static void main(String []args){
        final List<String> list=new ArrayList<String>();
        final List<String> synList=Collections.synchronizedList(list);
        final Object o=new Object();
        Thread tOne=new Thread(new Runnable(){

            @Override
            public void run() {
                //synchronized(o){
                for(int i=0;i<100;i++){
                    System.out.println(synList.add("add one"+i)+ " one");
                }
                //}
            }

        });

        Thread tTwo=new Thread(new Runnable(){

            @Override
            public void run() {
                //synchronized(o){
                for(int i=0;i<100;i++){
                    System.out.println(synList.add("add two"+i)+" two");
                }
                //}
            }

        });
        tOne.start();
        tTwo.start();
    }
}

我得到的输出是:

true one
true two
true one
true two
true one
true two
true two
true one
true one
true one...

在未注释显式同步块(synchronized block)的情况下,我将在添加时停止来自其他线程的干扰。一旦线程获得了锁,它就会一直执行直到完成。

取消注释同步块(synchronized block)后的示例输出:

true one
true one
true one
true one
true one
true one
true one
true one...

那么为什么 Collections.synchronizedList() 没有进行同步呢?

最佳答案

同步列表仅同步该列表的方法。

这意味着当另一个线程当前正在运行此列表中的方法时,一个线程将无法修改该列表。对象在处理方法时被锁定。

例如,假设有两个线程在您的列表上运行 addAll,有 2 个不同的列表(A=A1,A2,A3B=B1 ,B2,B3) 作为参数。

  • 由于方法是同步的,你可以确定这些列表不会像 A1,B1,A2,A3,B2,B3

  • 你不能决定一个线程何时将进程移交给另一个线程。每个方法调用都必须完全运行并返回,然后才能运行另一个。所以你可以得到 A1,A2,A3,B1,B2,B3B1,B2,B3,A1,A2,A3 (因为我们不知道哪个线程调用将首先运行)。

在您的第一段代码中,两个线程同时运行。两者都尝试将元素 add 到列表中。除了 add 方法上的同步之外,您没有任何方法可以阻止一个线程,因此没有什么可以阻止线程 1 在将进程移交给线程 2 之前运行多个 add 操作. 所以你的输出是完全正常的。

在您的第二段代码(未注释的代码)中,您明确声明一个线程在开始循环之前将列表与另一个线程完全锁定。因此,您要确保其中一个线程在另一个线程可以访问列表之前运行完整的循环。

关于java - Collections.synchronizedList() 方法有什么用?它似乎没有同步列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40930861/

相关文章:

java - 我可以使用 Maven 构建多个项目,然后通过 m2eclipse 运行 Jetty 吗?

c# - .net 应用程序多线程

c# - 如何正确处置 Form,而不会有从已处置对象上的另一个线程调用 Invoke 的风险?

c++ - 为多平台目的克隆 C++ 数据类型

java - TextToSpeech setLanguage 不起作用?

java - JMM 在实践中

java - Gradle 的 jar 中没有显示依赖项?

java - 为什么java中Collections的fill(),copy(),reverse(),shuffle()是这样实现的

magento - 在magento中加载模型哪种方式更好?

java - CopyOnWriteArrayList 可以与可变对象一起使用吗?