分段锁——ConcurrentHashMap
1、线程不安全的HashMap
因为多线程环境下,使用Hashmap进行put操作会引起死循环,导致CPU利用率接近100%,所以在并发情况下不能使用HashMap。
2、效率低下的HashTable容器
HashTable容器使用synchronized来保证线程安全,但在线程竞争激烈的情况下HashTable的效率非常低下。因为当一个线程访问HashTable的同步方法时,其他线程访问HashTable的同步方法时,可能会进入阻塞或轮询状态。如线程1使用put进行添加元素,线程2不但不能使用put方法添加元素,并且也不能使用get方法来获取元素,所以竞争越激烈效率越低。
3、ConcurrentHashMap分段锁技术
ConcurrentHashMap是Java 5中支持高并发、高吞吐量的线程安全HashMap实现。
我们以ConcurrentHashMap来说一下分段锁的含义以及设计思想,ConcurrentHashMap中的分段锁称为Segment,类似于HashMap(JDK7与JDK8中HashMap的实现)的结构,即内部拥有一个Entry数组,数组中的每个元素又是一个链表;同时又是一个ReentrantLock(Segment继承了ReentrantLock)。
当需要put元素的时候,并不是对整个hashmap进行加锁,而是先通过hashcode来知道他要放在哪一个分段中,然后对这个分段进行加锁,所以当多线程put的时候,只要不是放在一个分段中,就实现了真正的并行的插入。
但是,在统计size的时候,可就是获取hashmap全局信息的时候,就需要获取所有的分段锁才能统计。
分段锁的设计目的是细化锁的粒度,当操作不需要更新整个数组的时候,就仅仅针对数组中的一项进行加锁操作。
4、用法
模拟信息的发送和接收,场景是这样的:
服务器向客户端发送信息,要保证信息100%的发送给客户端,那么发给客户端之后,客户端返回一个消息告诉服务器,已经收到。当服务器一直没有收到客户端返回的消息,那么服务器会一直发送这个信息,直到客户端接收并确认该信息,这时候再删除重复发送的这个信息。
为了模拟该场景,这里写两个线程,一个是发送线程,一个是接收线程,把要发送的信息保存到线程安全的对象里面,防止发生线程安全问题,这里采用ConcurrentHashMap。
a、SendThread:信息重新发送类
package com.lynch.lock;import java.util.Map.Entry;/** *** @author Lynch */ public class SendThread extends Thread {@Overridepublic void run() {try {sleep(6000);while (ConcurrentHashMapTest.pushMessage.size() > 0) {for (Entry<Integer, String> hashMap : ConcurrentHashMapTest.pushMessage.entrySet()) {System.out.println("消息id:" + hashMap.getKey()+ "未发送成功,在此重发:" + hashMap.getValue());}sleep(1000);}} catch (InterruptedException e) {e.printStackTrace();}} }
b、ReceiveThread:信息接收类
package com.lynch.lock;import java.util.Map.Entry;/*** 接收发送过来的信息,并从内存中删除* * @author Administrator**/ public class ReceiveThread extends Thread {@Overridepublic void run() {try {for (int i = 0; i < 100000; i++) {sleep(2000);for (Entry<Integer, String> map : ConcurrentHashMapTest.pushMessage.entrySet()) {if (map.getKey() == i) {System.out.println("成功收到id为:" + map.getKey() + "返回的信息,删除该元素");ConcurrentHashMapTest.pushMessage.remove(map.getKey());}}System.out.println("内存对象中的元素数量为:" + ConcurrentHashMapTest.pushMessage.size());}} catch (InterruptedException e) {e.printStackTrace();}} }
c、ConcurrentHashMapTest:主类入口
package com.lynch.lock;import java.util.concurrent.ConcurrentHashMap;/*** 模拟信息的发送和接收** @author Lynch*/ public class ConcurrentHashMapTest {public static ConcurrentHashMap<Integer, String> pushMessage = new ConcurrentHashMap<Integer, String>();public static void main(String[] args) {for (int i = 0; i < 5; i++) {pushMessage.put(i, "该消息是id为" + i + "的消息");}Thread sendThread = new SendThread();Thread receiveThread = new ReceiveThread();sendThread.start();receiveThread.start();for (int i = 5; i < 10; i++) {pushMessage.put(i, "该消息是id为" + i + "的消息");}} }
这样两个线程可以轮流的进行各自的事情,并且不会造成数据安全的问题。用这种方式,再结合Androidpn的推送机制,会更加符合实际生产中的应用。
转载于:https://www.cnblogs.com/linjiqin/p/5131667.html
分段锁——ConcurrentHashMap相关推荐
- Java中的锁机制 -- 乐观锁、悲观锁、自旋锁、可重入锁、读写锁、公平锁、非公平锁、共享锁、独占锁、重量级锁、轻量级锁、偏向锁、分段锁、互斥锁、同步锁、死锁、锁粗化、锁消除
文章目录 1. Java中的锁机制 1.1 乐观锁 1.2 悲观锁 1.3 自旋锁 1.4 可重入锁(递归锁) 1.5 读写锁 1.6 公平锁 1.7 非公平锁 1.8 共享锁 1.9 独占锁 1.1 ...
- 面试官:ConcurrentHashMap为什么放弃了分段锁?
今天我们来讨论一下一个比较经典的面试题就是 ConcurrentHashMap 为什么放弃使用了分段锁,这个面试题阿粉相信很多人肯定觉得有点头疼,因为很少有人在开发中去研究这块的内容,今天阿粉就来给大 ...
- JAVA8的ConcurrentHashMap为什么放弃了分段锁,有什么问题吗,如果你来设计,你如何 设计。
jdk8 放弃了分段锁而是用了Node锁,减低锁的粒度,提高性能,并使用CAS操作来确保Node的一些操作的原子性,取代了锁. 但是ConcurrentHashMap的一些操作使用了synchroni ...
- 【转】ConcurrentHashMap分段锁原理
前言:在分析ConcurrentHashMap的源码的时候,了解到这个并发容器类的加锁机制是基于粒度更小的分段锁,分段锁也是提升多并发程序性能的重要手段之一. 在并发程序中,串行操作是会降低可伸缩性, ...
- 我使出这“三板斧”(分段锁、哈希锁、弱引用锁)灭霸跑了......
有同学说,学了Java那么多锁,还是没能锁住灭霸,本文教你"三板斧",锁灭霸足矣. 据说,没几个人能真正参透这"三板斧"的精髓,你是不是那个有缘人呢? 最近,在 ...
- Java 中15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁,乐观锁,分段锁,自旋锁等等...
http://blog.51cto.com/13919357/2339446 Java 中15种锁的介绍 在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类.介绍的内容 ...
- go 并发安全map 分段锁实现
一. 简言 1.1 go中的map不是并发安全的 1.2 go1.9版本之前,可以使用map+mutex的方式实现并发安全,但是每次操作,无论读取都要加锁,性能不太好 1.3 go 1.9之后,新增了 ...
- Java 中15种锁的介绍:公平锁,可重入锁,独享锁,互斥锁,乐观锁,分段锁,自旋锁等等
Java 中15种锁的介绍 在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类.介绍的内容如下: 公平锁 / 非公平锁 可重入锁 / 不可重入锁 独享锁 / 共享锁 互 ...
- 2019最新拼多多Java面试题:幻影读+分段锁+死锁+Spring Cloud+秒杀
拼多多Java一面 简短自我介绍 事务的ACID,其中把事务的隔离性详细解释一遍 脏读.幻影读.不可重复读 红黑树.二叉树的算法 平常用到哪些集合类?ArrayList和LinkedList区别?Ha ...
- 可重入锁/不可重入锁,公平锁/非公平锁,乐观锁/悲观锁,独享锁/共享锁,偏向锁/轻量级锁/重量级锁,分段锁,自旋锁
在并发编程中,会涉及到各种各样的锁,这篇文章主要介绍各种锁的分类以及作用. 介绍的内容如下: 可重入锁/不可重入锁 公平锁/非公平锁 乐观锁/悲观锁 独享锁/共享锁 偏向锁/轻量级锁/重量级锁 分段锁 ...
最新文章
- C#编程概念系列(一):面向对象编程
- HDU 2102 A计划
- java 多线程间通讯_JAVA多线程间通讯常用实现方法解析
- python queue_Python-Queue 入门
- Oracle Schema Objects——Tables——TableType
- linux gunzip r .tar,Linux命令之文件归档、压缩、解压缩tar,gzip,gunzip,bzip2,bunz -电脑资料...
- 15个Linux Yum命令实例--安装/卸载/更新
- 设计模式——解释器模式
- dw1560_【兵哥小课堂】Big Sur安装情况汇总以及DW1820A/DW1560在Big Sur中的正确插入姿势...
- 【HDU1411】四面体的体积公式
- 十年前与十年后的我们,流着泪看完的经典语录!
- 崔希凡-javaWeb-笔记day07-day09(2016年7月26日23:17:27)
- IT6801FN图像质量调优
- 【Java】多人协同在线编辑Excel源代码及部署包
- 智能汽车里究竟“藏”有多少传感器?
- 计算机毕业设计ssm东湖爱心系统的众筹设计和实现t4a84系统+程序+源码+lw+远程部署
- 25、Java面向对象——抽象类和抽象方法、接口
- HCIP第九天笔记(OSPF的路由回馈、路由策略、以及配置指南)
- 【POI2013】bzoj3426 Tower Defence Game
- css单位vw vh,css3自适应布局单位vw,vh详解