Vector vs Collections.synchronizedList(ArrayList)

sub*_*his 36 java collections vector arraylist

Vector是同步的,ArrayList不是同步的,但是我们可以同步一个ArrayList Collections.synchronizedList(aList),这样会更好更快地执行吗?

loc*_*cka 5

同步收集既浪费时间又危险。一个很简单的例子,为什么它们不好,是考虑两个线程在同一集合上同时运行一个循环:

int i = 0;
while (i < list.size())
{
  if (testSomeCondition(list.get())) {
    list.remove(i);
  else
    i++;
}
Run Code Online (Sandbox Code Playgroud)

我们的列表可能是同步的(例如,Vector),并且此代码仍将严重破坏。为什么?因为对size(),get(),remove()的单个调用是同步的,但是一个线程仍可以从列表中删除项目,而另一个线程对其进行迭代。换句话说,我们有一个竞争条件,使用同步集合并没有给我们带来任何好处。

为了解决这个问题,我们必须同步集合上的整个操作,或者使用Java 5并发锁来做到这一点。

synchronized (list) {
  int i = 0;
  while (i < list.size())
  {
    if (testSomeCondition(list.get())) {
      list.remove(i);
    else
      i++;
  }
}
Run Code Online (Sandbox Code Playgroud)

现在,此代码块是线程安全的,因为一次只能有一个线程可以执行循环。现在,没有理由使用同步集合。我们可以使用ArrayList代替Vector,并节省所有同步调用的性能损失。

因此,请勿使用同步集合。如果发现自己有多个线程在同一个列表中,则需要保护列表中的操作,而不是单个调用。

  • “同步收集是浪费时间。” -太笼统了。同步集合有一个目的。您只是在举例说明如何错误地使用它们。稻草人争吵。 (12认同)
  • 此回复无法回答问题。相反,它说不用担心线程安全的集合。 (7认同)
  • 作为公认的答案,这没有任何意义。 (3认同)
  • 他们确实是在浪费时间。即使集合由单个线程独占使用,synchronized 关键字也会造成调用损失。大多数集合将由单个线程独占使用。即使它们是共享的,同步单个调用仍然会出现竞争条件,因此它们不适合目的。开发人员只是浪费时间在他们所谓的线程安全集合中寻找错误。简而言之,这些集合是有毒的,除非无法避免(例如遗留案例、J2ME 等),否则永远不要使用它们。 (2认同)
  • java 1.3 及更早版本中的同步速度很慢。在现代java中它更好。http://www.ibm.com/developerworks/java/library/j-jtp04223/index.html 另外,再次使用稻草似是而非的论点。没有人在已知的单线程情况下使用同步。你的第一个例子只是简单的糟糕编程,没有任何集合可以弥补这一点。无论您使用什么集合,您都必须考虑什么是原子的,什么不是原子的。看一下ArrayList中的remove()代码,你就会明白为什么这个方法需要同步来保持列表的完整性。 (2认同)