ArrayList vs Vector语言 - 这是否说明了同步的差异



>我试图理解ArrayList和Vector的行为差异。以下代码片段是否以任何方式说明了同步的差异?ArrayList (f1( 的输出是不可预测的,而 Vector (f2( 的输出是可预测的。我认为 f2 具有可预测的输出可能只是运气,因为稍微修改 f2 以使线程休眠甚至一毫秒 (f3( 会导致一个空向量!这是什么原因造成的?

public class D implements Runnable {
   ArrayList<Integer> al;
   Vector<Integer> vl;
   public D(ArrayList al_, Vector vl_) {
      al = al_;
      vl = vl_;
   }
   public void run() {
      if (al.size() < 20)
         f1();
      else
         f2();
   } // 1
   public void f1() {
      if (al.size() == 0)
         al.add(0);
      else
         al.add(al.get(al.size() - 1) + 1);
   }
   public void f2() {
      if (vl.size() == 0)
         vl.add(0);
      else
         vl.add(vl.get(vl.size() - 1) + 1);
   }
   public void f3() {
      if (vl.size() == 0) {
         try {
            Thread.sleep(1);
            vl.add(0);
         } catch (InterruptedException e) {
            System.out.println(e.getMessage());
         }
      } else {
         vl.add(vl.get(vl.size() - 1) + 1);
      }
   }
   public static void main(String... args) {
      Vector<Integer> vl = new Vector<Integer>(20);
      ArrayList<Integer> al = new ArrayList<Integer>(20);
      for (int i = 1; i < 40; i++) {
         new Thread(new D(al, vl), Integer.toString(i)).start();
      }
   }
}

要回答这个问题:是的,向量是同步的,这意味着对数据结构本身的并发操作不会导致意外行为(例如 NullPointerExceptions 或其他东西(。因此,像 size() 这样的调用在并发情况下使用 Vector 是完全安全的,但在ArrayList情况下则不是(请注意,如果只有读取访问,ArrayLists也是安全的,一旦至少一个线程写入数据结构,我们就会遇到问题,例如添加/删除(

问题是,这种低级同步基本上是完全无用的,你的代码已经证明了这一点。

if (al.size() == 0)
   al.add(0);
else
   al.add(al.get(al.size() - 1) + 1);

您在这里想要的是根据当前大小向数据结构添加一个数字(即,如果 N 个线程执行此操作,最终我们希望列表包含数字[0..N)(。可悲的是,这不起作用:

假设 2 个线程在空列表/向量上并发执行此代码示例。以下时间表是很有可能的:

T1: size() # go to true branch of if
T2: size() # alas we again take the true branch.
T1: add(0)
T2: add(0) # ouch

两者都执行size()并返回值 0。然后,它们进入 的真正分支,并将0添加到数据结构中。那不是你想要的。

因此,无论如何,您都必须在业务逻辑中同步,以确保size()add()以原子方式执行。因此,矢量的同步在几乎任何情况下都是毫无用处的(与现代 JVM 上的一些声明相反,无争议锁的性能影响完全可以忽略不计,但集合 API 要好得多,所以为什么不使用它(

在The Beginning(Java 1.0(中,有"同步向量"。

这会带来潜在的巨大性能打击。

因此,在Java 1.2之后添加了"ArrayList"和friends。

您的代码首先说明了使矢量同步的基本原理。 但大多数时候根本不需要这样做,其余大部分时间最好以其他方式完成。

恕我直言...

附注:一个有趣的链接:

http://www.coderanch.com/t/523384/java/java/ArrayList-Vector-size-incrementation

向量是线程安全的。ArrayLists不是。这就是为什么ArrayList比向量更快。下面的链接有关于这个的很好的信息。

http://www.javaworld.com/javaworld/javaqa/2001-06/03-qa-0622-vector.html

我试图了解数组列表的行为差异 和矢量

Vectorsynchronized,而ArrayList不是。 ArrayList不是线程安全的。

以下代码片段是否以任何方式说明了 同步?

没有区别,因为只有Vectorsunchronized

相关内容

最新更新