并发编程-13线程安全策略之两种类型的同步容器

简介: 并发编程-13线程安全策略之两种类型的同步容器

2019080611330380.jpg


脑图

20190223152151128.png



概述


上篇 并发编程-12线程安全策略之常见的线程不安全类讲了一些常用的线程不安全的集合容器(ArrayList、HashMap、HashSet),如果有多个线程并发访问这些集合时就会出现线程不安全的问题。 当我们在使用这些容器时,需要我们自己来处理线程安全的问题。 使用起来相对会有些不便,而Java在这方面提供了相应的同步容器,我们可以在多线程情况下可以结合实际场景考虑使用这些同步容器。


同步容器


20190223154601865.png


集合接口下的同步容器实现类

  • Vector的方法都是由synchronized关键字保护


2019022315483053.png



20190223155014932.png

ctrl + o,方法左侧,就可以看出是个同步方法。


Stack继承了Vector,并且提供了栈操作(先进后出)

20190223154514708.png


Hashtable也是由synchronized关键字保护


20190223154718914.png


Vector (线程安全性比ArrayList好一些,但并非绝对线程安全)

ArrayList线程不安全的例子:

https://blog.csdn.net/yangshangwei/article/details/87887613#ArrayList__121


20190223155442315.png

运行结果:

20190223155502579.png


这种情况下 ,多线程 计算结果正确


同步容器 线程不安全的场景


同步容器也并不一定是绝对线程安全的,例如有两个线程,线程A根据size的值循环执行remove操作,而线程B根据size的值循环执行执行get操作。它们都需要调用size获取容器大小,当循环到最后一个元素时,若线程A先remove了线程B需要get的元素,那么就会报越界错误


Vector中的方法都进行了同步处理,那么一定就是线程安全的,事实上这可不一定 。来演示下


20190223170301268.png

运行结果: java.lang.ArrayIndexOutOfBoundsException

20190223170458160.png

我们来分析一下:

Vector是线程安全的,为什么还会报这个错?对于Vector,虽然能保证每一个时刻只能有一个线程访问它,但是不排除这种可能:


当某个线程在某个时刻执行这句时:

for(int i=0;i<vector.size();i++){
   vector.get(i);
}

假若此时vector的size方法返回的是10,i的值为9

然后另外一个线程执行了这句:

for(int i=0;i<vector.size();i++){
  vector.remove(i);
}


将下标为9的元素删除了, 那么通过get方法访问下标为9的元素肯定就会出问题了。

因此为了保证线程安全,必须在方法调用端做额外的同步措施


20190223171737984.png

其他注意事项

当我们使用foreach循环或迭代器去遍历元素的同时又执行删除操作的话,即便在单线程下也会报并发修改异常.

20190223233636866.png


所以在foreach循环或迭代器遍历的过程中不能做删除操作,若需遍历的同时进行删除操作的话尽量使用for循环。实在要使用foreach循环或迭代器的话应该先标记要删除元素的下标,然后最后再统一删除. 如果使用JDK8,可以使用函数式编程

20190223172919779.png


Hashtable

线程不安全的HashMap

https://blog.csdn.net/yangshangwei/article/details/87887613#HashMap__130


20190223173501543.png

运行结果:


20190223173521866.png


Collections.synchronizedXXX方法所创建的同步容器


Collections类中提供了多个synchronizedXxx方法, 该方法返回指定集合对象对应的同步对象,从而可以解决多线程并发访问集合时的线程安全问题


20190223213937663.png


Collections.synchronizedList


20190223220338336.png


运行结果: 线程安全

20190223220559457.png


Collections.synchronizedMap



20190223220703524.png


运行结果: 线程安全

20190223220718714.png

Collections.synchronizedSet


2019022322080175.png


运行结果: 线程安全


20190223220812469.png

小结


同步容器是通过synchronized来实现同步的,所以性能较差。而且同步容器也并不是绝对线程安全的,在一些特殊情况下也会出现线程不安全的行为。那么有没有更好的方式代替同步容器呢?----> 那就是**并发容器,有了并发容器后同步容器的使用也越来越少的,大部分都会优先使用并发容器(J.U.C)**. 下篇博文我们讨论下J.U.C


总之一句话,优先使用并发容器提供的集合,而不是使用加了锁的同步容器中的集合


代码


https://github.com/yangshangwei/ConcurrencyMaster

相关文章
|
3月前
|
编解码 数据安全/隐私保护 计算机视觉
Opencv学习笔记(十):同步和异步(多线程)操作打开海康摄像头
如何使用OpenCV进行同步和异步操作来打开海康摄像头,并提供了相关的代码示例。
131 1
Opencv学习笔记(十):同步和异步(多线程)操作打开海康摄像头
|
1月前
|
存储 缓存 监控
Docker容器性能调优的关键技巧,涵盖CPU、内存、网络及磁盘I/O的优化策略,结合实战案例,旨在帮助读者有效提升Docker容器的性能与稳定性。
本文介绍了Docker容器性能调优的关键技巧,涵盖CPU、内存、网络及磁盘I/O的优化策略,结合实战案例,旨在帮助读者有效提升Docker容器的性能与稳定性。
111 7
|
1月前
|
安全 Java 开发者
Spring容器中的bean是线程安全的吗?
Spring容器中的bean默认为单例模式,多线程环境下若操作共享成员变量,易引发线程安全问题。Spring未对单例bean做线程安全处理,需开发者自行解决。通常,Spring bean(如Controller、Service、Dao)无状态变化,故多为线程安全。若涉及线程安全问题,可通过编码或设置bean作用域为prototype解决。
34 1
|
2月前
|
Java 调度
Java 线程同步的四种方式,最全详解,建议收藏!
本文详细解析了Java线程同步的四种方式:synchronized关键字、ReentrantLock、原子变量和ThreadLocal,通过实例代码和对比分析,帮助你深入理解线程同步机制。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
Java 线程同步的四种方式,最全详解,建议收藏!
|
3月前
|
安全 Java 开发者
Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用
本文深入解析了Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用。通过示例代码展示了如何正确使用这些方法,并分享了最佳实践,帮助开发者避免常见陷阱,提高多线程程序的稳定性和效率。
58 1
|
3月前
|
安全 调度 C#
STA模型、同步上下文和多线程、异步调度
【10月更文挑战第19天】本文介绍了 STA 模型、同步上下文和多线程、异步调度的概念及其优缺点。STA 模型适用于单线程环境,确保资源访问的顺序性;同步上下文和多线程提高了程序的并发性和响应性,但增加了复杂性;异步调度提升了程序的响应性和资源利用率,但也带来了编程复杂性和错误处理的挑战。选择合适的模型需根据具体应用场景和需求进行权衡。
|
3月前
多线程通信和同步的方式有哪些?
【10月更文挑战第6天】
148 0
|
5月前
|
开发者 C# UED
WPF与多媒体:解锁音频视频播放新姿势——从界面设计到代码实践,全方位教你如何在WPF应用中集成流畅的多媒体功能
【8月更文挑战第31天】本文以随笔形式介绍了如何在WPF应用中集成音频和视频播放功能。通过使用MediaElement控件,开发者能轻松创建多媒体应用程序。文章详细展示了从创建WPF项目到设计UI及实现媒体控制逻辑的过程,并提供了完整的示例代码。此外,还介绍了如何添加进度条等额外功能以增强用户体验。希望本文能为WPF开发者提供实用的技术指导与灵感。
188 0
|
27天前
|
监控 NoSQL 时序数据库
《docker高级篇(大厂进阶):7.Docker容器监控之CAdvisor+InfluxDB+Granfana》包括:原生命令、是什么、compose容器编排,一套带走
《docker高级篇(大厂进阶):7.Docker容器监控之CAdvisor+InfluxDB+Granfana》包括:原生命令、是什么、compose容器编排,一套带走
190 77
|
1月前
|
监控 Docker 容器
在Docker容器中运行打包好的应用程序
在Docker容器中运行打包好的应用程序

热门文章

最新文章