多线程基础4(哈希表及死锁问题)

Hashtable

  • 直接在方法上加synchronized,相当于对this加锁,等同于对哈希表对象加锁,那么一个哈希表就只有一个锁;

  • 当存在多个线程时,无论这些线程是如何操作哈希表的,都会产生锁冲突问题;

  • 一旦触发扩容,就由该线程完成整个扩容过程,此过程涉及到大量元素拷贝,效率低下。

ConcurrentHashMap

相较于Hashtable,ConcurrentHashMap做出了很多优化:

  • 锁粒度控制:每个哈希桶都有自己的锁,降低锁冲突提高效率;

  • 只给写操作加锁,不给读操作加锁,两个线程同时修改才会有锁冲突;

  • 由于上述操作线程不一定安全,ConcurrentHashMap保证读到完整数据(新数据或者旧数据),读操作中也广泛使用volatile保证读到的数据是及时的;

  • 充分利用到CAS特性,能不加锁就不加锁,或者使用CAS实现的轻量级锁来实现;

  • 对扩容操作进行优化,化整为零,扩容期间旧的和新的数组会同时存在一段时间,进行哈希表操作时,会将旧的内存上的元素搬一部分到新的空间上,搬完释放旧空间,查询元素时新旧一起查,删除元素则直接删除不用进行搬运,插入元素直接往新数组加。

HashMap、HashTbale、ConcurrentHashMap区别

  • HashMap: 线程不安全;

  • Hashtable: 线程安全,使用 synchronized 锁 Hashtable 对象, 效率较低。

  • ConcurrentHashMap: 线程安全;使用 synchronized 锁每个链表头结点, 每个哈希桶都有自己的锁,降低锁冲突提高效率;充分利用CAS 机制;优化了扩容方式。

死锁

  • 概念:线程加锁后无法解锁,线程被无限期阻塞,不能继续往下执行;

  • 情况1:一个线程一把锁连续加锁两次:如果是不可重入锁就是死锁;

  • 情况2:两个线程两把锁;

  • 情况3:先给钱再交货和先交货再给钱 。

  • 死锁成立的必要条件:互斥使用(锁的基本特性);不可抢占(锁的基本特性);请求和保持(可打破);循环等待(可打破)。只要打破其中一个就可以解决死锁问题。

解决死锁方法

  • 请求和保持,即当资源请求者在请求其他的资源的同时保持对原有资源的占有,这个情况可以根据代码编写适当调整,但不能完全保证不发生此种情况。

  • 破坏循环等待,约定好加锁顺序,进行锁排序避免循环等待,加多个锁时先加编号小的锁,后加编号大的锁。

  • 操作系统中的”银行家算法“也能解决死锁问题,将所有资源进行统筹分配。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值