如何解决并发环境下集合的线程安全问题?

一、Synchronized、ReentrantReadWriteLock、CopyOnWrite

1.Synchronized:如果使用Synchronized关键字来保证线程安全的话,线程的并发度是最小的,因为读读、读写、写写线程都不能并发执行

2.ReentrantReadWriteLock:如果使用读写锁来保证线程安全,线程的并发度会稍好一些,因为读写、写写线程不能并发执行,但是读读线程可以并发执行

3.CopyOnWrite:如果采用COW思想来保证线程安全,线程的并发度会比以上两种方式都好,因为除了写写线程不能并发执行外,读读、读写线程都可以并发执行。这里以CopyOnWriteArrayList为例, 写线程首先会尝试获取可重入锁ReentrantLock,保证在同一时刻只有一个线程可以进行写操作;之后将原始数组的数据复制到新数组中后添加新内容,最后使旧数组的引用指向新数组。在这个过程中读写线程可以并发执行,但缺点是读线程读到的可能不是最新的实时数据,即它通过牺牲数据的实时一致性来保证线程的并发度以及数据的最终一致性 参考资料

线程并发度排序:Synchronized<ReentrantReadWriteLock<CopyOnWrite

二、ArrayList部分

1.使用Vector代替ArrayList:Vector是线程安全的

List<String> list=new Vector<>();

2.使用Collections.synchronizedList()将ArrayList转换为线程安全的

List<String> list=Collections.synchronizedList(new ArrayList<>());

3.CopyOnWrite:使用时复制的思想

List<String> list=new CopyOnWriteArrayList<>();

总结 :1、2这两种方式都是采用Java关键字synchronzied对方法进行修饰,利用独占式锁来保证线程安全的。但是独占式锁会导致同一时刻只有一个线程能够获取到对象监视器,很显然这种方式效率并不是太高。CopyOnWriteArrayList的底层存储结构是数组

三、HashSet部分

1.使用Collections.synchronizedSet()将HashSet转换为线程安全的

Set<String> set=Collections.synchronizedSet(new HashSet<>());

2.CopyOnWrite:使用时复制的思想

Set<String> set=new CopyOnWriteArraySet<>();

总结:HashSet的底层结构是HashMap,就是用了HashMap的Key部分(不重复),CopyOnWriteArraySet的底层存储结构是CopyOnWriteArrayList

四、HashMap部分

1.使用Collections.synchronizedMap()将HashMap转换为线程安全的

Map<String,String> map=Collections.synchronizedMap(new HashMap(16,0.75));//初始容量和加载因子**

2.创建一个并发的HashMap,ConcurrentHashMap不会接受Key为null和Value为null的情况,否则会抛出空指针异常

Map<String,String> map=new ConcurrentHashMap<>();

おすすめ

転載: blog.csdn.net/qq_40714246/article/details/118894229