当前位置: 首页 > 面试题库 >

Collections.synchronizedList()方法的用途是什么?似乎没有同步列表

慕翰学
2023-03-14
问题内容

我正在尝试使用两个线程将String值添加到中ArrayList。我想要的是,当一个线程正在添加值时,另一个线程不应干涉,因此我使用了该Collections.synchronizedList方法。但是看来,如果我没有在对象上显式同步,则添加操作将以不同步的方式进行。

没有显式的同步块:

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...

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

取消注释同步块后的样本输出:

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
add在将进程移交给线程2之前运行多个操作。因此,您的输出是完全正常的。

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



 类似资料:
  • 我正在尝试使用两个线程将值添加到。我想要的是,当一个线程添加值时,另一个线程不应该干扰,所以我使用了 方法。但是,如果我不显式同步对象,则添加似乎是以不同步的方式完成的。 没有显式同步块: 我得到的输出是: 通过取消对显式synchronized块的注释,我在添加时停止了来自其他线程的干扰。一旦线程获得了锁,它就一直执行,直到完成。 取消注释同步块后的示例输出: 那么,为什么<code>集合会出现

  • 问题内容: 我在dos.oracle.com上找到了这个 公共静态列表syncedList(列表列表) 返回由指定列表支持的同步(线程安全)列表。为了保证串行访问,至关重要的是,对后备列表的所有访问都必须通过返回的列表来完成。当用户遍历返回列表时,必须手动对其进行同步: 我的问题是:如果应该返回已经同步的列表,为什么我必须同步列表以对其进行迭代? 我只是在两个线程中访问列表:一个线程只是添加,另一

  • 问题内容: 我正在尝试使用以下代码来理解: 产生输出: 什么是和这里?文档说明中说: 返回指定的文字模式。 此方法产生一个,可用来创建一个与字符串相匹配的,就好像它是文字模式一样。 输入序列中的元字符或转义序列将没有特殊含义。 但是的返回类型不是编译对象。 为什么需要此方法?使用示例有哪些? 问题答案: 表示“文字文本的开始”(即正则表达式“开引号”) 表示“文字文本的结束”(即正则表达式“闭引号

  • 我对python还很陌生,我正在尝试创建21点。然而,当我试图打印出玩家的手牌时,我遇到了一些困难。 这是我的击球(抽牌)代码: 这是我打印卡片的代码: 我的代码所做的第一件事是为庄家和玩家抽两张牌,这运行得很好。然而,当玩家抽到一张牌后,它就会变得有点摇摆不定。输出如下所示: 当我抽到一张新牌时,这张牌不变,它保持我抽到的最后一张牌。然后,当我打印我的甲板,它打印我的旧甲板和我的新甲板。但是,分

  • 问题内容: 可以说我们有以下两个示例代码: 还有这个 所以有人可以告诉我现在有什么区别吗? 问题答案: 这两种不同的方法在 功能上是等效的 。有 可能 是一个非常小的 性能 差异: 在字节码级别,作为方法访问标记中设置的位, 同步方法 公布其同步需求。JVM查找该位标志并进行适当同步。 该 同步块 通过存储在该方法的类文件中的字节码定义的操作序列实现其同步。 因此,同步方法 可能会以 更快的速度执

  • 本文向大家介绍JavaScript中Object.isFrozen()方法的用途是什么?,包括了JavaScript中Object.isFrozen()方法的用途是什么?的使用技巧和注意事项,需要的朋友参考一下 Object.isFrozen() Object.isFrozen()方法用于查找对象是否冻结。  如果符合以下条件,则对象被冻结 它不应是可扩展的。 它的属性应该是 不可配置的。 它不应