动力节点旗下在线教育品牌  |  咨询热线:400-8080-105 学Java全栈,上蛙课网
首页 > 文章

多线程中的同步容器和并发容器

06-23 18:10 183浏览
举报 T字号
  • 大字
  • 中字
  • 小字

Java并发编程中,我们经常听到同步容器、并发容器之说,我们不禁发出疑问:什么是同步容器与并发容器

同步容器可以简单地理解为通过synchronized来实现同步的容器。同步容器会导致多个线程中对容器方法调用的串行执行,降低并发性,因为它们都是以容器自身对象为锁,所以在需要支持并发的环境中,可以考虑使用并发容器来替代。并发容器是针对多个线程并发访问而设计的,在jdk5.0引入了concurrent包,其中提供了很多并发容器,如ConcurrentHashMap、CopyOnWriteArrayList等。

同步容器的出现是由于使用容器时进行同步处理的不便。Java的集合容器框架中,主要四大类是List、Set、Queue、Map。其中List、Set、Queue分别继承了Collection顶层接口,Map本身是一个顶层接口。我们常用的ArrayList、LinkedList、HashMap这些容器都是非线程安全的,如果有多个线程并发访问这些容器时,就会出现问题。因此,编写程序时,必须要求开发者手动在任何访问到这些容器的地方进行同步处理,这样导致使用这些容器时的不便,所以,Java提供了同步容器供用户使用。同步容器将所有对容器状态的访问都串行化了,保证线程安全性的同时严重降低了并发性,当多个线程竞争容器时,吞吐量严重降低。从JDK5开始针对多线程并发访问设计,提供了并发性能较好的并发容器,引入了java.util.concurrent 包。

同步容器与并发容器都为多线程并发访问提供了合适的线程安全,不过并发容器的可扩展性更高。在Java5之前,程序员们只有同步容器,且在多线程并发访问的时候会导致争用,阻碍了系统的扩展性。Java5介绍了并发容器,并发容器使用了与同步容器完全不同的加锁策略来提供更高的并发性和伸缩性,例如,在ConcurrentHashMap中采用了一种粒度更细的加锁机制,可以称为分段锁,在这种锁机制下,允许任意数量的读线程并发地访问map,并且执行读操作的线程和写操作的线程也可以并发的访问map,同时允许一定数量的写操作线程并发地修改map,所以它可以在并发环境下实现更高的吞吐量,另外,并发容器提供了一些在使用同步容器时需要自己实现的复合操作,包括putIfAbsent等,但是由于并发容器不能通过加锁来独占访问,所以我们无法通过加锁来实现其他复合操作了。

java中的同步容器类:

1、Vector、Stack、HashTable

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

Vector实现了List接口,其实际上就是一个类似于ArrayList的数组,但Vector中的方法都是synchronized方法。Stack也是同步容器,实际上Stack是继承于Vector。HashTable也进行了同步处理,但HashMap没有。Collections类是一个工具提供类,其中包含对集合或容器进行排序、查找等操作的方法。重要的是,它也提供了几个静态工厂方法来创建同步容器类。同步容器不可避免地也会存在一些缺陷,同步容器中的方法采用了synchronized进行同步,这会影响执行性能。而且同步容器不一定是真正完全的线程安全,同步容器中的方法是线程安全的,但对这些集合类的符合操作无法保证其线程安全性,仍旧需要通过主动加锁来保证。Vector等容器迭代时同时对其修改时同步容器会出现 ConcurrentModificationException异常。在多线程情况下为了避免这种异常可以在使用iterator迭代的时候,使用synchronized或lock同步、使用并发容器CopyOnWriteArrayList代替ArrayList和Vector。

ConcurrentHashMap代替同步的Map。HashMap是根据散列值分段存储,同步Map在同步时锁住了所有的段,而ConcurrentHashMap加锁的时候根据散列值锁住了散列值对应的那段,提高了并发性能。ConcurrentHashMap提供了对常用符合操作的支持。比如"若没有则添加":putIfAbsent(),替换:replace()。这2个操作都是原子操作。与Vector和Hashtable、Collection.synchronizedXxx()同步容器等相比,util.concurrent中的并发容器可以根据具体场景设计,尽量避免synchronized,提供并发性,与此同时,可以定义一些并发安全的复合操作,并且保证并发环境下的迭代操作不会出错。util.concurrent中容器在迭代时,可以不封装在synchronized中,可以保证不抛异常,但未必每次看到的都是最新的数据。

并发容器是为了解决同步容器的性能问题,提高了程序的吞吐量。而同步容器则是为了实现java多线程访问非线程安全的容器时的同步性。两者相辅相成,缺一不可。只有熟练掌握并发容器和同步容器,才能完整得实现多线程的并发性和同步性,在多线程的性能提升的同时保证线程安全。

0人推荐
共同学习,写下你的评论
0条评论
HHADA
程序员HHADA

3篇文章贡献16991字

作者相关文章更多>

推荐相关文章更多>

Java数据结构

HelloWorld10-31 08:24

浅谈MySQL中SQL优化的常用方法

军哥08-12 23:29

五分钟读懂UML类图

江湖人称小李白12-10 10:41

MyBatis开发框架的四大核心

IT逐梦者08-17 21:43

一次搞定continue,break和return

HelloWorld11-06 11:19

发评论

举报

0/150

取消