文章目录

  • 脑图
  • 概述
  • 同步容器
    • 集合接口下的同步容器实现类
      • Vector (线程安全性比ArrayList好一些,但并非绝对线程安全)
      • 同步容器 线程不安全的场景
      • 其他注意事项
      • Hashtable
    • Collections.synchronizedXXX方法所创建的同步容器
    • Collections.synchronizedList
    • Collections.synchronizedMap
    • Collections.synchronizedSet
  • 小结
  • 代码

脑图


概述

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


同步容器


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

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


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


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

  • Hashtable也是由synchronized关键字保护

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

ArrayList线程不安全的例子:
https://blog.csdn.net/yangshangwei/article/details/87887613#ArrayList__121

运行结果:

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


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

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

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

运行结果: java.lang.ArrayIndexOutOfBoundsException

我们来分析一下:

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的元素肯定就会出问题了。

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


其他注意事项

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

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


Hashtable

线程不安全的HashMap
https://blog.csdn.net/yangshangwei/article/details/87887613#HashMap__130

运行结果:


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

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

Collections.synchronizedList


运行结果: 线程安全


Collections.synchronizedMap

运行结果: 线程安全


Collections.synchronizedSet

运行结果: 线程安全


小结

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

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


代码

https://github.com/yangshangwei/ConcurrencyMaster

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

  1. 并发编程-12线程安全策略之常见的线程不安全类

    文章目录 脑图 概述 字符串拼接子之StringBuilder.StringBuffer StringBuilder (线程不安全) StringBuffer (线程安全) 小结 时间相关的类 Sim ...

  2. 并发编程-11线程安全策略之线程封闭

    文章目录 脑图 概述 线程封闭的三种方式 示例 堆栈封闭 ThreadLocal Step1. ThreadLocal操作类 Step2. 自定义过滤器 Step3. 注册拦截器,配置拦截规则 Ste ...

  3. Java并发编程一线程池的五种状态

    推荐:Java并发编程汇总 Java并发编程一线程池的五种状态 原文地址 Java多线程线程池(4)–线程池的五种状态 正文 线程池的5种状态:Running.ShutDown.Stop.Tidyin ...

  4. 并发编程-10线程安全策略之不可变对象

    文章目录 脑图 四个线程安全策略 不可变对象定义 不可变对象需要满足的条件 如何创建不可变对象 使用final关键字定义不可变对象 修饰变量示例 final修饰基本数据类型及String: 初始化之后 ...

  5. 并发编程-14线程安全策略之并发容器(J.U.C)中的集合类

    文章目录 J.U.C总览 脑图 概述 并发容器特性 示例 ArrayList对应的线程安全的并发容器类CopyOnWriteArrayList (线程安全) HashSet对应的线程安全的并发容器类C ...

  6. 19、Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition

    Java并发编程:线程间协作的两种方式:wait.notify.notifyAll和Condition 在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者 ...

  7. 并发编程-04线程安全性之原子性Atomic包的4种类型详解

    文章目录 线程安全性文章索引 脑图 概述 原子更新基本类型 Demo AtomicBoolean 场景举例 原子更新数组 Demo 原子更新引用类型 Demo 原子更新字段类型 使用注意事项: Dem ...

  8. [转]Java并发编程:线程池的使用

    Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题: 如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了, ...

  9. 泥瓦匠聊并发编程:线程与多线程必知必会(基础篇)

    本文目录 线程与多线程 线程的运行与创建 线程的状态 1 线程与多线程 线程是什么? 线程(Thread)是一个对象(Object).用来干什么?Java 线程(也称 JVM 线程)是 Java 进程 ...

最新文章

  1. PCB天线无线模组如何布局摆放?
  2. AIphaCode 并不能取代程序员,而是开发者的工具
  3. GPT-3距离下一代AI生态平台还有多远?
  4. 一文详解「群体机器人」中的「实体进化」到底是什么?
  5. oracle top用法
  6. xadmin 更改后台一级目录名称
  7. DFT泄露问题和DFT的频率轴表示方法(第三章离散傅里叶变换(3.8,3.13.4)学习笔记)
  8. C++中const关键字的使用总结
  9. Repeater简单应用(动态改变内部样式)
  10. mybatis SqlMapConfig.xml mappers
  11. Linux学习笔记 -- rpm 与 shell 编程
  12. jQuery-表单验证使用方法
  13. python句柄无效_使用pyinstaller打包,subprocess报“句柄无效”错误的解决方法
  14. CSDN愈来愈金钱化
  15. 魅族4usb计算机连接,魅族MX4如何连接电脑 魅族MX4连接电脑方法
  16. 关于计算机的英语小品,英文好玩简短的小品
  17. 淘宝佣金冻结-JS解决方案
  18. 从 smali 接入第三方 sdk
  19. 大脑状态的重构与认知行为之间的映射
  20. mysql连接字符串配置_配置数据库连接字符串ConnectionString

热门文章

  1. git stash 个人理解
  2. Pangolin在cmake时报“Could NOT find GLEW”错误
  3. 149. Leetcode 1005. K 次取反后最大化的数组和 (贪心算法-基础题目)
  4. 两个单链表生成相加链表
  5. Python~爬虫~2(requests)
  6. pytorch笔记:实例解析NLLLoss和CrossEntropyLoss
  7. R语言实战应用精讲50篇(十八)-R语言实现分词、词频与词云案例解析
  8. 最新技术资讯,你必须知道的Python 3.9新功能
  9. pycharm同一目录下无法import其他文件
  10. NLP通用模型decaNLP诞生,一个模型搞定十大自然语言常见任务