`
talentluke
  • 浏览: 593570 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

Vector 是线程安全的?

 
阅读更多

Vector 是否是线程安全的?因为框架大量使用 RMI,RMI 是天生非线程安全的,所以作者认为采用了 Vector 来声明成员变量后,类就是 Thread-safe 了。

或许,大家经常也碰到类似的问题:Vector 与 ArrayList 的区别?
好多人一拍脑门就出:Vector 是线程安全的 (在任何情况下都是)。。。

原因可能是因为 Vector 的所有方法加上了 synchronized 关键字,从而保证访问 vector 的任何方法都必须获得对象的 intrinsic lock (或叫 monitor lock),也即,在vector内部,其所有方法不会被多线程所访问。
但是,以下代码呢:

if (!vector.contains(element)) 
    vector.add(element); 
    ...
}

这是经典的 put-if-absent 情况,尽管 contains, add 方法都正确地同步了,但作为 vector 之外的使用环境,仍然存在  race condition: 因为虽然条件判断 if (!vector.contains(element))与方法调用 vector.add(element);  都是原子性的操作 (atomic),但在 if 条件判断为真后,那个用来访问vector.contains 方法的锁已经释放,在即将的 vector.add 方法调用 之间有间隙,在多线程环境中,完全有可能被其他线程获得 vector的 lock 并改变其状态, 此时当前线程vector.add(element);  正在等待(只不过我们不知道而已)。只有当其他线程释放了 vector 的 lock 后,vector.add(element); 继续,但此时它已经基于一个错误的假设了。

单个的方法 synchronized 了并不代表组合(compound)的方法调用具有原子性,使 compound actions  成为线程安全的可能解决办法之一还是离不开
intrinsic lock (这个锁应该是 vector 的,但由 client 维护)

// Vector v = ...
    public  boolean putIfAbsent(E x) {
synchronized(v) { 
            boolean absent = !contains(x); 
            if (absent) { 
                add(x);

}
        return absent; 
    }

所以,正确地回答那个“愚蠢”的问题是:
Vector 和 ArrayList 实现了同一接口 List, 但所有的 Vector 的方法都具有 synchronized 关键修饰。但对于复合操作,Vector 仍然需要进行同步处理。 

这样做的后果,Vector 应该尽早地被废除,因为这样做本身没有解决多线程问题,反而,在引入了概念的混乱的同时,导致性能问题,因为 synchronized 的开销是巨大的:阻止编译器乱序,hint for 处理器寄存一/二级缓存。。。

分享到:
评论
6 楼 charles751 2017-06-18  
分析的很好!
但有一点:只要同步组合操作就可以了,不一定非要synchronzed(Vector)。
5 楼 S346618898 2016-02-26  
core Java中有一段:
Vector类对自己的所有可修改方法
都使用内部锁。然而,这是真的吗? Vector类的文档没有给出这样的承诺。不得不仔细研究源
代码并希望将来的版本能介绍非同步的可修改方法。如你所见,客户端锁定是非常脆弱的,通
常不推荐使用。
4 楼 xd2008ck 2015-08-18  
各自有各自的场景吧
楼主不要太激进了
3 楼 zwt2001267 2015-05-10  
写的不错,赞一个
2 楼 primer_of_java 2014-04-29  
楼主善于思考这点是很不错的. 点赞.
最近在面试的时候我遇到了让我写多线程,然后我使用了vector,果然也遇到了楼主描述的这个问题,因此不得不用同步块来完成原子操作~~
1 楼 fortunely 2014-04-24  
分析得不错,学习了,赞一个。
那最主要的区别其实是不是就是Vector的每个函数实现都加了sychronized关键字

相关推荐

    线程安全Vector

    线程安全!~~涉及到vector的操作问题,以及在多线程中应该注意的事项.

    vector线程中的应用

    关于线程安全的介绍,vector的线程安全性,vector的相关操作。线程安全性的操作.

    Go-golang-set-Go的线程安全的和非线程安全的高性能集

    golang-set - Go的线程安全的和非线程安全的高性能集

    Java集合多线程安全.docx

    Java集合多线程安全 线程安全与不安全集合 线程不安全集合: ArrayList LinkedList HashMap HashSet TreeMap TreeSet StringBulider 线程安全集合: Vector HashTable Properties 集合线程安全...

    java集合-Vector的使用

    但需要注意的是,Vector是线程安全的,在多线程环境下可以进行并发操作。如果不需要线程安全性,并且希望更高的性能,可以使用ArrayList。 需要注意的是,从Java 1.2开始,推荐使用ArrayList代替Vector,因为...

    Java经典的List面试题目

    Java经典的List面试题目: 1、你知道的 List 都有哪些? 2 、List 和 Vector 有什么区别? 3 、List 是有序的吗?...7 、List 是线程安全的吗?如果要线程安全要怎么做? 8、怎么给 List 排序? ......

    JavaSE 笔试 精华

    StringBuffer是线程安全的,StringBuilder不是线程安全的。 2、Anonymous Inner Class (匿名内部类) 是否可以extends(继承)其它类,是否可以implements(实现)interface(接口) 答:匿名的内部类是没有名字的内部类。...

    Java 最常见的 208 道面试题:第二模块答案

    Java 最常见的 208 道面试题:第二模块答案 18. java 容器都有哪些?...30. 哪些集合类是线程安全的? 31. 迭代器 Iterator 是什么? 32. Iterator 怎么使用?有什么特点? 33. Iterator 和 ListIterator 有什么区别?

    电信面试题

    备注:对于Vector&ArrayList、Hashtable&HashMap,要记住线程安全的问题,记住Vector与Hashtable是旧的,是java一诞生就提供了的,它们是线程安全的,ArrayList与HashMap是java2时才提供的,它们是线程不安全的。...

    srzyhead#ReadingNote#13-线程安全与锁优化1

    绝对线程安全Vector的get()、remove()和size(),如果另一个线程恰好在错误的时间里删除了一个元素,导致序号i已经不再可用的话,再用i访问数组

    Java集合教程吐血整理干货.md

    线程安全的集合 线程安全的 List CopyOnWriteArrayList 线程安全的Set 线程安全的Map ConcurrentHashMap ConcurrentSkipListMap java集合 线程不安全的集合 HashMap的特点 HashMap在Jdk8之前使用拉链法实现,jdk8...

    JAVA-面试题大全(含答案)

    它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector中的方法由于添加了synchronized修饰,因此Vector是线程安全的容器,但性能上较ArrayList差,因此...

    你知道synchronizedList和Vector底层原理实现和区别吗?其实开始我也不知道!(超详细源码分析)

    因为Vector和ArrayList除了数组扩容有点差别,还有加锁使Vector迈进了线程安全的行列外,底层实现大约是没有太大区别的!基本一致!线程安全问题更是另当别论了!继续往下看就OK! 扩容的区别: 从内部实现机制来讲...

    Java集合框架完整说明便于了解集合

    HashMap 和 Hashtable 的区别,HashSet如何检查重复,HashMap的底层实现,HashMap 多线程操作导致死循环问题,ConcurrentHashMap 和 Hashtable 的区别,ConcurrentHashMap线程安全的具体实现⽅式/底层具体实现,...

    Java并发编程相关源码集 包括多任务线程,线程池等.rar

     volatile关键字的非原子性、volatile关键字的使用、AtomicInteger原子性操作、线程安全小例子:多个线程竞争问题、多个线程多个锁问题、创建一个缓存的线程池、多线程使用Vector或者HashTable的示例(简单线程同步...

    Java常见面试题208道.docx

    47.在 java 程序中怎么保证多线程的运行安全? 48.多线程锁的升级原理是什么? 49.什么是死锁? 50.怎么防止死锁? 51.ThreadLocal 是什么?有哪些使用场景? 52.说一下 synchronized 底层实现原理? 53....

    JAVA面试基础知识题

    同步性:Vector是线程安全的,也就是说是同步的,而ArrayList是线程序不安全的,不是同步的 二.数据增长:当需要增长时,Vector默认增长为原来一培,而ArrayList却是原来的一半 就HashMap与HashTable主要从三方面来说。...

    史上最全java面试,103项重点知识,带目录

    30. 哪些集合类是线程安全的? 12 31. 迭代器 Iterator 是什么? 12 32. Iterator 怎么使用?有什么特点? 12 33. Iterator 和 ListIterator 有什么区别? 13 三、多线程 13 35. 并行和并发有什么区别? 13 36. 线程...

    Java容器类List、ArrayList、Vector及map、HashTable应用

    List、ArrayList、Vector及map、HashTable、HashMap的区别与用法 使用容器排序 Vector由于使用了synchronized方法(线程安全)

Global site tag (gtag.js) - Google Analytics