面试官问我同步容器(如Vector)的所有操作一定是线程安全的吗?我懵了!

作者:媒体转发 时间:2019-08-29 01:36

字号

=

面试官问我同步容器(如Vector)的所有操作一定是线程安全的吗?我懵了!

为了方便编写出线程安全的程序,Java里面提供了一些线程安全类和并发工具,比如:同步容器、并发容器、阻塞队列等。

最常见的同步容器就是Vector和Hashtable了,那么,同步容器的所有操作都是线程安全的吗?

这个问题不知道你有没有想过,本文就来深入分析一下这个问题,一个很容易被忽略的问题。

1.同步容器

在Java中,同步容器主要包括2类:

1、Vector、Stack、HashTable

2、Collections类中提供的静态工厂方法创建的类

本文拿相对简单的Vecotr来举例,我们先来看下Vector中几个重要方法的源码:

public synchronized boolean add(E e) { 

    modCount++; 

    ensureCapacityHelper(elementCount + 1); 

    elementData[elementCount++] = e; 

    return true

 

public synchronized E remove(int index) { 

    modCount++; 

    if (index >= elementCount) 

        throw new ArrayIndexOutOfBoundsException(index); 

    E oldValue = elementData(index); 

 

    int numMoved = elementCount - index - 1; 

    if (numMoved > 0) 

        System.arraycopy(elementData, index+1, elementData, index

                         numMoved); 

    elementData[--elementCount] = null; // Let gc do its work 

 

    return oldValue; 

 

public synchronized E get(int index) { 

    if (index >= elementCount) 

        throw new ArrayIndexOutOfBoundsException(index); 

 

    return elementData(index); 

可以看到,Vector这样的同步容器的所有公有方法全都是synchronized的,也就是说,我们可以在多线程场景中放心的使用单独这些方法,因为这些方法本身的确是线程安全的。但是,请注意上面这句话中,有一个比较关键的词:单独因为,虽然同步容器的所有方法都加了锁,但是对这些容器的复合操作无法保证其线程安全性。需要客户端通过主动加锁来保证。简单举一个例子,我们定义如下删除Vector中最后一个元素方法:

public Object deleteLast(Vector v){ 

    int lastIndex  = v.size()-1; 

    v.remove(lastIndex); 

上面这个方法是一个复合方法,包括size()和remove(),乍一看上去好像并没有什么问题,无论是size()方法还是remove()方法都是线程安全的,那么整个deleteLast方法应该也是线程安全的。但是时,如果多线程调用该方法的过程中,remove方法有可能抛出ArrayIndexOutOfBoundsException。

Exception in thread "Thread-1" java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 879 

    at java.util.Vector.remove(Vector.java:834) 

    at com.hollis.Test.deleteLast(EncodeTest.java:40) 

    at com.hollis.Test$2.run(EncodeTest.java:28) 

    at java.lang.Thread.run(Thread.java:748) 

责任编辑:CQITer新闻报料:400-888-8888   本站原创,未经授权不得转载
关键词 >>线程 安全 容器
继续阅读
热新闻
推荐
关于我们联系我们免责声明隐私政策 友情链接