• ConcurrentHashMap 同步安全 的真正含义(stringbuff 是同步安全的,stringbutter 不安全)


    同步安全的集合,在多线程下用到这个map是安全的,但这个安全指的是什么?线程安全指的是指get、remove、put等操作时即同一对象,同一时间只有一个线程能在这几个方法上运行,也就是说线程安全是在这集合的三个操作基础上是线程安全的,但由于集合往往都和迭代器组合起来用,比如集合的遍历,一般都是和itator组合用,即itator是一个对象,这个对象里有当前索引位置(初始索引为0即集合第一个下标)和上一个索引位置(初始为-1,即集合第一个下标的前一个下标,第一个下标为0,那前一个下标 当然是-1)和理想迭代的数量(这个属性不知道干什么用的)以及集合的引用,就是说这个itato对象有四个属性,其中前2个属性用来迭代用的,第三个属性不知道干啥用的,第四个属性就是原来集合的一个镜像,最终迭代完就是通过这第四个镜像来同步原来的集合用的,线程安全安全就是体现在这里,假如一个集合是不安全的,那这个集合在遍历时假如itator中第四个属性即原集合的镜像在一个线程里是删除(目前只测试了删除会报错,get方法忘记测试了)操作,在另外一个线程里是加入一个元素,结果2个线程同步原集合时就会出现少加或者多加等莫名其妙的问题(在map遍历时能否进行元素的删除,修改可以,但删除有的map可以有的则不行,不行的map删除必报错:java.util.ConcurrentModificationException ,比如hashMap、list 等 集合是不安全 集合,遍历时是不能删除的,而 ConcurrentHashMap 是多线程安全的map集合,遍历时就可以删除。至于为啥不能删除上边说了原因,就是因为hashmap、list等遍历时是通过itator 遍历的,而其遍历时是元素是不可逆的,而且枷锁的,当正遍历时如有其中一个删除,第四个属性镜像同步外部的list 或者 hashmap 时 由于找不到 list或者hashmap中的对应元素就会报错。),而有个map是线程安全的,就不用担心这个问题,至于怎么个不用担心,原因是遍历时不用迭代器还是通过其他方式保证安全我不知道,反正就不用关心出错就行。还有就是 不管这个map是不是线程安全的,假如map就是线程安全的,多线程下还是要加这个同步锁,因为map自身的线程安全不是指这一方面的安全(上边讲了线程安全的意义),假如这个集合在多线程下有改动,还是需要synchronize 锁住的,不然多线程下,集合中的一个对象在这个线程中修改成那个值,在这个线程下修改为这个值,2个线程下这个对象值不一致,不可控,结果肯定也是数据错乱问题,所以在业务中仍然还应该要加锁  。    那不安全的集合啥时候用呢,一个是单线程下可以用,但仍不可以遍历时删除,还一个就是 比如基础模板封装的集合,这个集合只会 get不会删除,这种情况可以选择非同步安全的集合。所以不管单线程还是多线程,几乎最好都用线程安全的集合(集合只用来get 不会删除的除外可以用非安全的集合,如游戏基础数据存放的集合)。

    补:集合线程安全不安全除了上边说的遍历时删除会报错,即出现不安全的问题,还有就是多线程间调用同一个集合,修改集合中的同一个对象属性时,如果是多线程同时修改的话,第四个属性同步时也会出现不安全的报错问题。

  • 相关阅读:
    Go 笔记之如何防止 goroutine 泄露
    调试 Go 的代码生成
    使用k8s容器钩子触发事件
    springboot教程
    Intellij IDEA 使用Spring-boot-devTools无效解决办法
    c# WMI获取机器硬件信息(硬盘,cpu,内存等)
    各式 Web 前端開發工具整理
    Informix 中执行多条SQL(Execute Script)
    Log4Net
    mysql 按年度、季度、月度、周、日SQL统计查询
  • 原文地址:https://www.cnblogs.com/wzhanke/p/4399605.html
Copyright © 2020-2023  润新知