目录
HashTable与ConcurrentHashMap的区别
进入到线程模块 必不可少的就是接触到线程安全的数据结构 例如StringBuffer、BlockingQueue、PriorityBlockingQueue 等等 今天要了解的是HashTable、ConcurrentHashMap
HashTable
底层其实还是跟HashMap一样的 但是他在每次修改的时候都加了锁 所以能够保证每次在对于HashTable中的内容进行修改的时候线程安全 对于读的操作不会产生线程不安全的问题 所以不会处理 但是因为每次进行修改都要加锁 频繁加锁的话消耗是比较大的 所以此处理方式不推荐 效率会大大的进行折扣
HashMap
我们在之前的博客已经详细的介绍过了HashMap 并且也认真的分析过了源码等等 如果想要对于HashMap进行了解可以点击跳转
《数据解构》HashMap源码解读http://t.csdn.cn/WgPAg
ConcurrentHashMap
·底层采用的数组加链表
·本质还是与HashMap一致
·主要采用的是分段思想 会将一个长度为N的数组分割为N组 每一组单独使用一个锁
`加锁策略与HashTale不同 ConcurrentHashMap是对于单个key进行加锁的 可以看看下方绘图理解
错误原因的出现
此处如果两个线程对于同一个key进行修改 此处会出现线程安全问题 对于修改会出现只有一个生效
此处ConcurrentHashMap的处理策略就是对于每个key都加锁
HashTable与ConcurrentHashMap的区别
相同:在出发点上 都是为了保证线程安全的
不同:加锁策略不同 HashTable是对于整个进行加锁 ConcurrentHashMap是对于单个位置进行加锁 所以说 ConcurrentHashMap的效率是优于HashTable的 (此处的效率提升体现在两个线程痛死修改不同位置的元素中)ConcurrentHashMap是对于同一个位置的元素修改 是跟HashTable效率一样的
我们也配一个形象的例子 假设你现在去银行办理业务 我们此时提供了16个窗口 当你进入到一个窗口的时候 这个窗口便会加锁 只为你一个人提供服务 别人是无法进入的 每个窗口都是同样的道理
那么HashTable是什么样子呢 也就是一个银行只对于一个人服务 当你进入银行的时候 哗啦 把窗帘往下一拉 门一锁 那么此时 别人也想到银行办理业务就只能等待 等待你办理完业务 拉开窗帘打开门之后才可以使用
(因为源码比较繁琐 就不拿出来单独解释了 源码中的区别也是体现在HashTable是对于put方法整个加锁的 而ConcurrentHashMap是取出位置后才进行加锁的)
- ConcyrrentHashMap减少了锁冲突 就让锁加到每个链表的头节点上 (锁桶)
- ConcurrentHashMap只是针对写操作加锁了 读操作没加锁 而只是使用了volatile
- ConcurrentHashMap中更广泛的使用CAS 进一步提高效率
- ConcyrrentHashMap针对扩容 进行了巧妙的化整为零