为什么不同步会使ArrayList更快,更不安全?

时间:2011-05-19 15:34:46

标签: java concurrency arraylist

我读了以下声明:

  

ArrayLists是不同步的,因此比Vector快,但在多线程环境中安全性较低。

我想知道为什么不同步可以提高速度,以及为什么安全性会降低?

6 个答案:

答案 0 :(得分:10)

我会尝试解决你的两个问题:

  

提高速度

如果ArrayList被同步并且多个线程同时尝试从列表中读取数据,则线程必须等待才能获得列表上的独占锁。通过使列表保持不同步,线程不必等待,程序将运行得更快。

  

不安全

如果多个线程同时读取写入列表,则线程可能具有列表的不稳定视图,这可能导致多线程程序不稳定。

答案 1 :(得分:2)

同步的全部意义在于它意味着在任何给定时间只有一个线程可以访问对象。以一盒巧克力为例。如果盒子是同步的(Vector),你首先到达那里,没有其他人可以拿到任何你拿到你的选择。如果盒子没有同步(ArrayList),任何走过的人都会抓住巧克力 - 它会消失得更快,但你可能得不到你想要的那些。

答案 2 :(得分:2)

  

ArrayLists是不同步的   因此比Vector快,但更少   在多线程环境中安全。

     

我想知道原因   不同步可以改善   速度,为什么它不那么安全?

当多个线程正在读/写共享内存位置时,由于缺少互斥和正确的可见性,程序可能会计算出错误的结果。因此,缺乏同步被认为是“不安全的”。杰里米·曼森的This blog post可能会对这个主题做出很好的介绍。

当JVM执行synchronized方法时,它确保当前线程对调用该方法的对象具有独占锁。类似地,当方法完成执行时,JVM释放执行线程持有的锁。同步方法提供互斥和可见性保证 - 并且对于执行代码的“安全”(即保证正确性)很重要。但是,如果只有一个线程访问对象的方法,则无需担心安全问题。尽管多年来JVM性能已得到改进,但无竞争同步(即仅由一个线程访问的对象的锁定/解锁)仍然需要非零时间量。对于不同步的方法,JVM不会支付额外的罚款 - 因此它们比同步的对应方法更快。

Vector迫使他们选择你。所有方法都是synchronized,很难错误地使用它们。但是当在单线程上下文中使用Vector时,您需要为不必要的额外同步付出代价。 ArrayList给你留下选择。在多线程上下文中使用时,由您(程序员)正确同步代码;但是当在单线程上下文中使用时,保证不会支付任何额外的同步开销。

此外,当最初填充集合时,随后读取ArrayList即使在多线程上下文中也会表现得更好。例如,请考虑以下方法:

public synchronized List<String> getList() {
    List<String> list = new Vector<String>();
    list.add("Foo");
    list.add("Bar");
    return Collections.unmodifiableList(list);
}

创建,填充列表,并安全地发布它的不可变视图。查看上面的代码很明显,此列表的所有后续使用都是读取,即使在多个线程使用时也不需要任何同步 - 对象实际上是不可变的。在这里使用Vector会导致同步开销,即使对于不需要它的读取也是如此;使用ArrayList代替会更好。

答案 3 :(得分:0)

由于这一事实,非阻塞数据结构将比阻止数据结构更快。使用阻塞数据结构,如果某个实体获取了资源,则一旦可用,另一个实体将需要时间来获取该相同资源。

但是,根据具体情况,在某些情况下这可能不太安全。争论的主要内容是写作期间。如果可以保证数据结构中包含的数据不会改变,则它已被添加,并且只有在读取值时才会被访问,而不会出现问题。当写入和读取或写入和写入之间存在冲突时,会出现问题。

答案 4 :(得分:0)

同步使用锁(或其他同步构造)的数据结构,以确保其数据始终处于一致状态。通常,这需要一个或多个线程在另一个线程上等待以完成更新结构的状态,这将降低性能,因为在没有之前已经引入了等待。

答案 5 :(得分:0)

2个线程可以同时修改列表并同时添加新项目或删除/修改列表中的相同项目,因为不存在同步(或锁定机制,如果您愿意)。所以想象一下,当其他人试图使用它时你删除列表中的一个项目,或者当有人使用它时你修改了一个项目,它不是很安全。

http://download.oracle.com/javase/1.4.2/docs/api/java/util/ArrayList.html
阅读“请注意,此实现未同步”。段落,它解释得更好。

我忘了,考虑到速度,想象当你试图控制对数据的访问时,你会添加一些阻止其他人访问你数据的机制,这似乎是微不足道的。因此,您添加了一些更多的计算,因此它更慢......