当前位置: 首页 > news >正文

网站不备案做seo没用沂水网站建设

网站不备案做seo没用,沂水网站建设,做微信公众号微网站吗,网站建设类别ConcurrentHashMap 是 HashMap 的多线程版本#xff0c;HashMap 在并发操作时会有各种问题#xff0c;比如死循环问题、数据覆盖等问题。而这些问题#xff0c;只要使用 ConcurrentHashMap 就可以完美解决了#xff0c;那问题来了#xff0c;ConcurrentHashMap 是如何保证…ConcurrentHashMap 是 HashMap 的多线程版本HashMap 在并发操作时会有各种问题比如死循环问题、数据覆盖等问题。而这些问题只要使用 ConcurrentHashMap 就可以完美解决了那问题来了ConcurrentHashMap 是如何保证线程安全的它的底层又是如何实现的接下来我们一起来看。 JDK 1.7 底层实现 ConcurrentHashMap 在不同的 JDK 版本中实现是不同的**在 JDK 1.7 中它使用的是数组加链表的形式实现的而数组又分为大数组 Segment 和小数组 HashEntry。**大数组 Segment 可以理解为 MySQL 中的数据库而每个数据库Segment中又有很多张表 HashEntry每个 HashEntry 中又有多条数据这些数据是用链表连接的如下图所示 JDK 1.7 线程安全实现 了解了 ConcurrentHashMap 的底层实现再看它的线程安全实现就比较简单了。接下来我们通过添加元素 put 方法来看 JDK 1.7 中 ConcurrentHashMap 是如何保证线程安全的具体实现源码如下 final V put(K key, int hash, V value, boolean onlyIfAbsent) {// 在往该 Segment 写入前先确保获取到锁HashEntryK,V node  tryLock() ? null : scanAndLockForPut(key, hash, value); V oldValue;try {// Segment 内部数组HashEntryK,V[] tab  table;int index  (tab.length - 1)  hash;HashEntryK,V first  entryAt(tab, index);for (HashEntryK,V e  first;;) {if (e ! null) {K k;// 更新已有值...}else {// 放置 HashEntry 到特定位置如果超过阈值则进行 rehash// 忽略其他代码...}}} finally {// 释放锁unlock();}return oldValue; }从上述源码我们可以看出Segment 本身是基于 ReentrantLock 实现的加锁和释放锁的操作这样就能保证多个线程同时访问 ConcurrentHashMap 时同一时间只有一个线程能操作相应的节点这样就保证了 ConcurrentHashMap 的线程安全了。也就是说 ConcurrentHashMap 的线程安全是建立在 Segment 加锁的基础上的所以我们把它称之为分段锁或片段锁如下图所示 JDK 1.8 底层实现 在 JDK 1.7 中ConcurrentHashMap 虽然是线程安全的但因为它的底层实现是数组 链表的形式所以在数据比较多的情况下访问是很慢的因为要遍历整个链表而 JDK 1.8 则使用了数组 链表/红黑树的方式优化了 ConcurrentHashMap 的实现具体实现结构如下 链表升级为红黑树的规则当链表长度大于 8并且数组的长度大于 64 时链表就会升级为红黑树的结构。 PSConcurrentHashMap 在 JDK 1.8 虽然保留了 Segment 的定义但这仅仅是为了保证序列化时的兼容性不再有任何结构上的用处了。 JDK 1.8 线程安全实现 在 JDK 1.8 中 ConcurrentHashMap 使用的是 CAS volatile 或 synchronized 的方式来保证线程安全的它的核心实现源码如下 final V putVal(K key, V value, boolean onlyIfAbsent) { if (key  null || value  null) throw new NullPointerException();int hash  spread(key.hashCode());int binCount  0;for (NodeK,V[] tab  table;;) {NodeK,V f; int n, i, fh; K fk; V fv;if (tab  null || (n  tab.length)  0)tab  initTable();else if ((f  tabAt(tab, i  (n - 1)  hash))  null) { // 节点为空// 利用 CAS 去进行无锁线程安全操作如果 bin 是空的if (casTabAt(tab, i, null, new NodeK,V(hash, key, value)))break; }else if ((fh  f.hash)  MOVED)tab  helpTransfer(tab, f);else if (onlyIfAbsent fh  hash ((fk  f.key)  key || (fk ! null  key.equals(fk))) (fv  f.val) ! null)return fv;else {V oldVal  null;synchronized (f) {// 细粒度的同步修改操作... }}// 如果超过阈值升级为红黑树if (binCount ! 0) {if (binCount  TREEIFY_THRESHOLD)treeifyBin(tab, i);if (oldVal ! null)return oldVal;break;}}}addCount(1L, binCount);return null; }从上述源码可以看出在 JDK 1.8 中添加元素时首先会判断容器是否为空如果为空则使用 volatile 加 CAS 来初始化。如果容器不为空则根据存储的元素计算该位置是否为空如果为空则利用 CAS 设置该节点如果不为空则使用 synchronize 加锁遍历桶中的数据替换或新增节点到桶中最后再判断是否需要转为红黑树这样就能保证并发访问时的线程安全了。我们把上述流程简化一下我们可以简单的认为在 JDK 1.8 中ConcurrentHashMap 是在头节点加锁来保证线程安全的锁的粒度相比 Segment 来说更小了发生冲突和加锁的频率降低了并发操作的性能就提高了。而且 JDK 1.8 使用的是红黑树优化了之前的固定链表那么当数据量比较大的时候查询性能也得到了很大的提升从之前的 O(n) 优化到了 O(logn) 的时间复杂度具体加锁示意图如下 总结 ConcurrentHashMap 在 JDK 1.7 时使用的是数据加链表的形式实现的其中数组分为两类大数组 Segment 和小数组 HashEntry而加锁是通过给 Segment 添加 ReentrantLock 锁来实现线程安全的。而 JDK 1.8 中 ConcurrentHashMap 使用的是数组链表/红黑树的方式实现的它是通过 CAS 或 synchronized 来实现线程安全的并且它的锁粒度更小查询性能也更高。
http://www.tj-hxxt.cn/news/136265.html

相关文章:

  • 如何创建网站小程序用wordpress搭建完整网站教程
  • 网站建设需要注意的问题wordpress the_terms
  • 如何查询网站的外链网站如何布局
  • 公明网站建设成品网站是什么
  • 北京企业网站建设公司哪家好网页设计广州网站
  • 企业网站搜索引擎拓客怎样做好营销推广
  • 怎么做购物优惠券网站网站视频外链怎么做
  • 网站优化公司免费咨询义马网站建设电话
  • 网站建设项目需求书葫芦岛手机网站建设
  • 网站架构招聘北京市专业网站建设
  • 创建一个网站多少钱网址导航已取消是什么意思
  • 深圳正规制作网站网站关键词优化有用吗
  • 全国建设市场公共服务网站南京家装公司有哪些品牌
  • 电脑网站和手机网站怎么做相同路径wordpress主题制作的书
  • 学校网站如何建设中山网站建设文化平台
  • 网站设置超链接云南省建设注册考试中心网站
  • 什么是网站维护免费的游戏大全
  • 电子商务网站建设研究安康升降平台
  • 网站收录一键提交莞城网站建设
  • 网站如何实现临时聊天qq网页版输入账号登录
  • 网站体验步骤wordpress做手机网站
  • 模板建站活动策划公司网站
  • 有做义工的相亲网站吗用啥网站做首页
  • 模块化网站开发口碑营销的例子
  • 可以做基因通路分析的网站小程序登录入口官网网址
  • 网站建设的公司哪家便宜wordpress外贸站
  • 河南焦作有做网站开发的公司吗怎么做网站卡盟
  • mui做网站网站正在建设中提示页面设计欣赏
  • 黄埔区做网站城乡住房和城乡建设部网站
  • 做的公司网站风格跟样式和别人一样中山网站设计公司