【问题标题】:java Vector and thread safetyjava向量和线程安全
【发布时间】:2009-11-01 23:03:03
【问题描述】:

我想知道这段代码是否会造成任何麻烦:

我有一个在许多线程之间共享的向量。每次线程必须从向量中添加/删除东西时,我都会在 synchronized 块下进行。但是,主线程有一个调用:

System.out.println("the vector's size: "+ vec.size());

不是synchronized

这会引起麻烦吗?

【问题讨论】:

  • 顺便说一句,您应该倾向于将 JDK 1.2 Collections API(ArrayList 或 LinkedList)与 Collections.synchronizedList(List) 结合使用以使它们同步。 Vector 已过时(与 Hashtable 一起)。
  • @Adamski 感谢您的评论,这对我帮助很大(虽然 3 岁)! ;)

标签: java vector multithreading thread-safety


【解决方案1】:

所有 Vector 方法本身都是同步的,因此只要您只围绕一个方法进行同步,您自己的同步就不是必需的。如果您有多个相互依赖的方法调用,例如vec.get(vec.size()-2) 之类的东西要获取倒数第二个元素,您必须使用自己的同步,否则,向量可能会在 vec.size() 和 vec.get() 之间变化。

【讨论】:

    【解决方案2】:

    我假设您指的是java.util.Vector

    其实Vector.size()同步的,会返回一个与向量状态一致的值(当调用size()的线程进入监视器时)如果返回42,那么在某个时间点向量正好包含 42 个元素。

    如果您在另一个线程的循环中添加项目,那么您无法预测确切的大小,但它应该可以用于监控目的。

    【讨论】:

    • +1 表示“在某个时间点”。可能与语句周围的代码不完全一致。为此,您需要添加自己的同步。
    【解决方案3】:

    java.util.Vector 的每个方法都是synchronized,所以这对于只记录大小的东西不会造成任何问题。

    为了提高性能,最好将Vector 替换为ArrayListArrayList的方法不是synchronized,所以你需要自己同步所有的访问。

    【讨论】:

    • 如果您将同步的 Vector 类替换为未同步的 ArrayList 并围绕 ArrayList 上的所有方法调用添加您自己的同步,您期望哪些性能改进?
    • 很多情况下,单方法同步是不够的,所以还是得自己做同步。使用 Vector,您最终会同步两次。
    • 如果您实现 synchronized(vec) {vec.get(vec.size()-2);} 之类的东西,您预计“双重”同步会对性能产生多大影响?
    • 如果您在向量本身上手动同步,那么开销可以忽略不计。如果您在另一个对象上进行同步,那么就会有更多的开销(我刚刚做了一些快速测试,结果显示 ArrayList 在这种情况下快 25%,并且没有线程争用)。
    【解决方案4】:

    请注意,您始终可以使用Collections.synchronizedCollection(Collection<T> c) 静态方法获取集合的同步版本..

    【讨论】:

    • 在这种情况下,集合是一个List,所以Collections.synchronizedList(List c)会更好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-12
    • 1970-01-01
    • 2020-06-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多