从HashMap到分库分表

HashMap概要

HashMap继承AbstractMap <K,V>,实现Map <K,V>,Cloneable,Serializable接口,提供put,get方法存取数据

HashMap数据结构

HashMap是由数组+链表构成,链表主要是为了解决哈希冲突问题即不同key的hash值可能一样(拉链法)。对于查找,如果定位到的数组不含链表,一次寻址即可,算法复杂度O(1),含有链表,需要用equals逐一比较,这个过程的算法复杂度O(n),jdk1.8以后做了优化,当链表长度大于阈值(TREEIFY_THRESHOLD = 8)且当前容量大于最小值(MIN_TREEIFY_CAPACITY = 64,小于则resize()),链表转化为红黑树,算法复杂度降为O(lgn)。

HashMap为什么线程不安全

内部方法未同步,哈希碰撞和哈希扩容的时候,出现线程不安全的情况。 哈希碰撞时候,线程A判断节点的next指针为null,这时候时间分片用完了,线程B进来了,也判断为null,然后线程A和B都建下一个节点,必然造成其中一个丢成。哈希扩容时候, 当多个线程同时检测到总数量超过门限值的时候就会同时调用resize操作,各自生成新的数组并rehash后赋给该map底层的数组table,结果最终只有最后一个线程生成的新数组被赋给table变量,其他线程的均会丢失。而且当某些线程已经完成赋值而其他线程刚开始的时候,就会用已经被赋值的table作为原始数组,这样也会有问题。

HashMap长度为2的幂次方

如果长度是2的幂次方,则hash%length = hash&(length -1)成立,与运算代替乘法运算,性能提升。

类比数据库的分库分表

如果我们把hashmap的过程和数据库分库分表水平拆分的hash法做类比,会发现很多思想上的共通性,我们完全可以把hashmap的这一套思想迁移过去,例如分成2的冥次方个表/库。

HashMap,HashTable的区别

HashMap线程不安全,HashTable线程安全,Hashtable内部方法基本都通过synchronized修饰,保证了可见性。但是Hashtable效率太低,当一个线程访问同步方法时,其他线程也访问同步方法,可能会进入阻塞或轮询状态.

HashTable类比表锁

HashTable和数据库悲观锁中的表锁大体类似。锁的太多,性能就差。

线程安全且效率高的ConcurrentHashMap

JDK1.7的时候,对Table进行了分割分段,每个Segment(ReentrantLock)锁住一部分Table,默认分配16个Segment,效率也就提升16倍。到了JDK1.8的时候,直接用 Node 数组+链表+红黑树的数据结构来实现,并发控制使用 synchronized 和 CAS 来操作。有几个node提升多少倍。

ConcurrentHashMap类比页锁,表锁

JDK1.7的时候,ConcurrentHashMap类似数据库悲观锁-页锁,JDK1.8则类似行锁,锁的数据越来越少,效率也就越来越高。

再说说ReentrantLock和Synchronized

两者都是可重入锁,即两者都是同一个线程没进入一次,锁的计数器都自增1,所以要等到锁的计数器下降为0时才能释放锁。区别的是ReentrantLock提供了创建公平锁的构造函数,ReentrantLock比较灵活,加锁解锁由用户自己控制,一般记得在finally里释放锁。

再说说Condition和Object

ReentrantLock获得锁后可以通过通过创建Condition对象来使线程wait,condition对象的signal方法可以唤醒wait线程,而notify(),notifyAll()是随机唤起一个。

到这里不得不提一嘴sleep和wait

sleep是Thread类的静态方法,不释放锁资源,休息指定时间后,恢复到就绪状态,wait是Object 类的方法,放弃锁进入等待池,notify(随机唤醒一个)/notifyAll唤起,才由等待池进入锁池,获得对象锁进入就绪状态。

再延伸一下到读写锁ReentrantReadWriteLock

readLock()获取读锁,writeLock获取写锁,读锁,此时多个线程可以或得读锁,写锁,此时只有一个线程能获得写锁,但读锁和写锁是互斥的,读锁释放后才执行写锁的方法,这个可以类比数据库中的读写锁,(in share mode/for update),这里不在赘述。

总结

很多知识点,类比之后我们能够理解的更加清晰,很多的思想其实都有共同之处。

文章出现谬误之处,希望大家指出,互相交流。

转载于:https://juejin.im/post/5c209e3a6fb9a049f91295d1

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值