【问题标题】:Vector vs Collections.synchronizedList(ArrayList)Vector vs Collections.synchronizedList(ArrayList)
【发布时间】:2011-02-22 09:53:42
【问题描述】:

Vector是同步的,ArrayList是不同步的但是我们可以通过Collections.synchronizedList(aList)来同步一个ArrayList,那么哪个会更好更快?

【问题讨论】:

  • 如果这是 C#,请用“C#”或“.NET”标记您的问题。
  • 你为什么不写一个测试并找出答案?
  • 你能解释一下使用模式吗? 1) 多写/多读 2) 少写多读 3) 多写少读 4) 少/少不需要优化

标签: java collections vector arraylist


【解决方案1】:

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

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

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

为了解决竞争,我们必须同步集合上的整个操作,或者使用 Java 5 并发锁来做同样的事情。

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

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

所以不要使用同步集合。如果您发现自己有多个线程访问同一个列表,那么您需要保护列表上的操作,而不是单个调用。

【讨论】:

  • "同步收集是浪费时间。" ——太笼统了。同步集合是有目的的。您只是在举例说明如何错误地使用它们。稻草人论据。
  • 从字面上看,他们是在浪费时间。即使集合仅由单个线程使用,同步关键字也会施加调用惩罚。大多数集合将由单个线程专门使用。即使它们是共享的,同步单个调用仍然允许竞争条件,因此它们不适合目的。开发人员只是浪费时间在他们所谓的线程安全集合中寻找错误。简单地说,这些集合是有毒的,除非无法避免(例如遗留案例、J2ME 等),否则永远不应使用它们。
  • java 1.3 及更早版本的同步速度很慢。在现代java中它更好。 ibm.com/developerworks/java/library/j-jtp04223/index.html 另外,再一次用稻草似的论据。没有人在已知为单线程的情况下使用同步。您的第一个示例只是简单的糟糕编程,没有任何集合可以弥补这一点。无论您使用什么集合,您都必须考虑什么是原子的或不是原子的。看看 ArrayList 中的 remove() 代码,你就会明白为什么需要同步这个方法来保持列表的完整性。
  • 世界充满了糟糕的编程。这个例子是为了简单地说明同步集合是一个有吸引力的麻烦,它实际上会导致错误——它们看起来很安全,但实际上并非如此。保护整个操作,内部使用非同步集合更高效、更明显、更安全。很明显,Sun 意识到了他们原来的类的问题,这就是为什么他们把它们推到一边,支持不同步的版本。
  • 此回复没有回答问题。相反,它说不要担心线程安全的集合。
猜你喜欢
  • 2014-01-24
  • 2013-01-17
  • 1970-01-01
  • 2023-04-04
  • 1970-01-01
  • 2014-12-18
  • 2016-09-08
  • 2021-02-27
  • 1970-01-01
相关资源
最近更新 更多