为什么在Java中使用同步集合很有用

时间:2011-01-06 15:00:44

标签: java

我知道ArrayList和Vector类之间的区别在于Vector类是同步的而ArrayList不是。我知道什么是同步,但有人可以解释它在这种情况下是如何有用的吗?

6 个答案:

答案 0 :(得分:4)

同步在Concurrency的上下文中使用。 This清楚地解释了为什么同步至关重要:

  

主要通过线程进行通信   共享对字段的访问权限   对象引用字段是指。   这种沟通方式是   效率极高,但两个   可能的错误类型:线程   干扰内存一致性   错误。该工具需要防止   这些错误是同步

同步的类/方法/实例/语句变量可防止并发使用同步的类/方法/实例/语句。

  

当一个线程正在执行a时   所有对象的同步方法   其他调用synchronized的线程   同一对象块的方法   (暂停执行)直到第一个   线程是用对象完成的。'

Source

向量是线程安全的(意味着已同步),而ArrayList则不是。您可以使用Collections.synchronizedList(...)

来确保线程安全

答案 1 :(得分:3)

public class ThreadSafeExample {
    private Vector<String> names = new Vector<String>();

    public void addName(String name) {
       names.add(name);
    }
}

即使多个线程调用addName(..)方法,此类也能正常工作。对于ArrayList,它不会 - 您将缺少值。

VectorArrayList的效果为benchmarked here。请注意,还存在Collections.synchornizedList(..)使任何列表同步。

请注意,当集合用作实例字段时,这适用。如果向量是在方法中声明的,那么同步化就无法获得任何结果(无论如何其他线程都无法使用它)。事实上,有一种称为“逃逸分析”的东西,在这种情况下,如果不需要,则会删除同步。但我认为默认情况下它没有开启。

答案 2 :(得分:1)

我不想重定向你,但我在这里也有同样的说法:http://manikandanmv.wordpress.com/2009/03/21/vector-vs-arraylist/

  

<强>矢量

     
      
  • Vector是线程安全的,因为矢量对象是同步的,这意味着您可以同时从任意数量的线程访问矢量对象,而不会影响其数据。
  •   
  • 由于上述原因,在性能方面,Vector比ArrayList
  • 稍慢   
  • 当内部阵列空间不足时,它的大小加倍。
  •   
     

<强>的ArrayList

     
      
  • ArrayList与Vector类正好相反。它不是线程安全的,假设您在多个线程中使用ArrayList实例肯定会导致在访问时产生一些问题。
  •   
  • ArrayList来自Collection Framework系列。因此,开发人员很容易转换为任何其他数据结构格式。
  •   
  • 将阵列大小增加50%。
  •   

ArrayList更受欢迎,您可以通过Collections.syncronizedList(..)

在外部同步它们

答案 3 :(得分:0)

如果多个线程可以同时访问它,则必须同步列表。如果只有一个线程可以访问列表,则同步是不必要的(但不一定是重要的)成本。

我个人倾向于默认使用ArrayList,并在需要时同步对它的访问。

使用公共列表&lt;&gt;用于引用Vector或ArrayList实例的接口允许您更轻松地切换实现。

答案 4 :(得分:0)

ArrayList旨在取代Vector,但它在设计上并非线程安全。我建议只使用ArrayList而不是使用Vector,因为它的设计不是集合的一部分。如果您在ArrayList上需要线程安全,则可以执行...

List list = Collections.synchronizedList(new ArrayList(...));

答案 5 :(得分:0)

你问同步对什么有用吗?你可能会喜欢Doug Lea的书Concurrent Programming in Java。虽然它有点过时,但它对访问相同数据结构的多个执行线程中固有的问题提供了良好的学术处理。对于实际应用和更新的治疗,您可以阅读Java Concurrency in Practice

正如Doug Lea所说,你希望执行线程取得进展。但您也希望保持数据结构的完整性。

对于Vector和ArrayList,假设有两个线程同时添加一个项目。需要做的事情之一是需要递增的项目数量。这是对你隐藏的东西,但对集合本身来说仍然很重要。在添加项目之前,ThreadA没有看到它,计数为3,并且尝试写入4,但同时ThreadB已经将它增加到4并且现在应该是5!

同步是解决此问题的一种方法。本质上,当两个线程尝试访问同一个对象并遇到“同步块”(有时可能是整个方法)时,ThreadB必须等到ThreadA完成并“释放锁定”。这样,两个线程没有机会读取计数,然后两个线程写入计数。通过强制执行线程的操作(同步它们),有一个读/写,然后是另一个读/写。