Java同步容器与并发容器

原创 2016年08月29日 18:15:03

Java容器

Java提供了很多容器类,方便用户使用。关键接口图如下(图片来源自The Java™ Tutorials),
Java core collection interfaces

  • Collection——集合框架结构的根节点。Java并没有提供该接口的具体实现,但是提供了Collection子接口,比如Set,List的具体实现。
  • Set——没有重复元素的集合。
  • List——有序的集合(或称为序列)。可以包括重复元素。
  • Queue——用于保存多个待处理的元素。典型地(但非必须),满足FIFO(先进先出)规则。
  • Deque——保存多个待处理的元素。支持先进先出(FIFO)和先进后出(LIFO)。双向,元素可以在两个方向添加或删除。
  • Map——将键(key)映射到值(value)的结构。不能包含相同的key,每个key至多映射到一个value。

同步容器类

我们平时用的ArrayList,Queue,HashMap,都不是同步安全的。如果我们在多个线程中这些类的实例,就可能发生线程干扰或内存一致性错误。

我们可以使用同步访问来解决这个问题,但是Java已经帮我们实现了,这就是接下来的同步容器类。同步容器类包括:

  • Vector和Hashtable,还有继承Vector的Stack类。
  • Collections.synchronizedXxx等工厂方法创建的类。

这些类实现线程安全的方法是:将它们的成员变量设置为私有(状态封装),并对每个公有方法都进行同步,使得每次只有一个线程能访问类的实例。

我们可以方便得使用这些同步容器来实现多个线程同步访问。但是并不意味同步容器可以完全保证线程安全。考虑以下的例子,

    public static Object getLast(Vector vector) {
        int lastIndex = vector.size() - 1;
        return vector.get(lastIndex);
    }

    public static void deleteLast(Vector vector) {
        int lastIndex = vector.size() - 1;
        vector.remove(lastIndex);
    }

这两个代码都会执行“先检查再运行”操作。先获得向量的大小,然后根据结果来得到或删除最后一个元素。如果这两个代码运行在两个线程中,会发生以下的执行序列,

  1. getLast得到向量大小,为10,
  2. deleteLast得到向量大小,为10,
  3. deleteLast删除最后一个元素,此时向量的大小为9
  4. getLast得到最后一个元素,get(9),但是由于deleteLast将最后一个元素删除,此时长度为9,所以此时会出错。

容器上常见的复合操作包括:迭代、跳转以及条件运算,例如“没有则添加”。在同步容器中,这些复合操作是线程安全的,但是在其他线程并发地修改容器时,就会发生意料之外的行为。比如上面的例子。

我们可以通过客户端加锁来解决该问题,使得getLast和deleteLast成为原子操作,确保vector的大小在调用size和get之间不会发生变化,示例代码如下:

    public static Object getLast(Vector vector) {
        synchronized (vector) {
            int lastIndex = vector.size() - 1;
            return vector.get(lastIndex);
        }
    }

    public static void deleteLast(Vector vector) {
        synchronized (vector) {
            int lastIndex = vector.size() - 1;
            vector.remove(lastIndex);
        }
    }

并发容器类

同步容器将所有对容器状态的访问都串行化,来实现线程安全性。这种方法的代价是严重降低并发性,当多个线程竞争容器的锁时,吞吐量将严重降低。

Java 提供了多种并发容器来改善同步容器的性能。另外,并发容器是针对多个线程并发访问设计的。

  • 替代Map的ConcurrentHashMap
  • 替代SortedMap的ConcurrentSkipListMap
  • 替代SortedSet的ConcurrentSkipListSet
  • 替代List的CopyOnWriteArrayList
  • ConcurrentLinkedQueue,先进先出队列
  • BlockingQueue,货站了Queue,支持可阻塞的插入和获取等操作
版权声明:本文为博主原创文章,未经博主允许不得转载。

Java同步容器和并发容器

同步容器 Java常用的容器有ArrayList、LinkedList、HashMap等等,这些容器都是非线程安全的。 如果有多个线程并发地访问这些容器时,就会出现问题。 因此,在编写程序时,必...
  • zhangzeyuaaa
  • zhangzeyuaaa
  • 2015年10月13日 10:46
  • 3092

菜鸟之路——Java并发(五)同步容器与并发容器

一、同步容器   在Java的集合容器框架中,主要有四大类别:List、Set、Queue、Map。List、Set、Queue接口分别继承了Collection接口,Map本身是一个接口。   注意...
  • sjjsh2
  • sjjsh2
  • 2016年11月22日 22:10
  • 1110

【JDK】:Java容器框架——同步容器与并发容器

前面的文章中详细介绍了Java的容器框架,在此基础上,本文对Java中的同步容器与并发容器做一些介绍。fail-fast机制快速报错机制(fail-fast)能够防止多个进程同时修改同一个容器的内容。...
  • u011080472
  • u011080472
  • 2016年05月15日 21:00
  • 2262

同步容器&并发下的容器

from:http://www.cnblogs.com/dolphin0520/p/3933404.html  为了方便编写出线程安全的程序,Java里面提供了一些线程安全类和并发工具,比如:同步...
  • basycia
  • basycia
  • 2016年07月28日 23:18
  • 965

同步类容器和并发类容器

同步类容器都是线程安全的,但在某些场景下可能需要加锁来保护复合操作,复合类操作 如:迭代(反复访问原始,遍历容器中所有的元素)、跳转(根据指定的顺序找到当前元素的下一个元素)、以及条件运算。这些复合操...
  • u010634288
  • u010634288
  • 2016年12月26日 21:29
  • 444

并发容器、同步容器、同步工具类

一、同步容器类 1.同步容器类包括Vector和Hashtable。这些类实现线程安全的方式是:将它们的状态封装起来,并对每个公有方法都进行同步,使得每次只有一个线程能够访问容器的状态。 2.同步容器...
  • yangnan0110
  • yangnan0110
  • 2015年04月13日 21:50
  • 310

多线程系列提高(5)--几种重要的并发容器类

ConcurrentHashMap、CopyOnWriteArrayList
  • L_kanglin
  • L_kanglin
  • 2017年04月16日 15:38
  • 447

java-并发-并发容器(3)

同样注意内层的第一个for循环,里面有语句int c = segments[i].count; 但是c却从来没有被使用过,即使如此,编译器也不能做优化将这条语句去掉,因为存在对volatile变量co...
  • youdianjinjin
  • youdianjinjin
  • 2016年07月23日 19:26
  • 877

JDK源码阅读 java.util.concurrent—并发容器类

JDK中java.util.concurrent实现了并发容器类,容器类的类图如下: BlockingQueue为接口,ArrayBlockingQueue,DelayQueue, Linke...
  • rommel1
  • rommel1
  • 2012年02月21日 01:18
  • 3285

java并发:同步容器&并发容器

第一节、同步容器与并发容器 1.简述同步容器与并发容器   在Java并发编程中,经常听到同步容器、并发容器之说,那什么是同步容器与并发容器呢?同步容器可以简单地理解为通过synchr...
  • youxia0075454
  • youxia0075454
  • 2017年03月08日 14:31
  • 188
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Java同步容器与并发容器
举报原因:
原因补充:

(最多只允许输入30个字)