IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【每日牛客面经】7.8_微店 -> 正文阅读

[数据结构与算法]【每日牛客面经】7.8_微店

1. 自我介绍

2. 了解ConcurrentHashMap吗?

concurrentHashMap的底层数据结构:在JDK1.7时,concurrentHashMap底层是用数组+链表实现的,在JDK1.8时,底层数据结构是用数组+链表+红黑树实现的

在实现线程安全方面:concurrentHashMap在JDK1.7时,concurrentHashMap采用的是分段锁的设计方式,对整个桶数组进行分割,设置一个segment,每一把锁只锁容器的一部门数据,多线程访问容器里不同数据端的数据,就不会存在锁竞争,提高并发率。

在JDK1.8时,摒弃了segment的概念,直接用Node数组+链表+红黑树的数据结构来实现,在多线程并发时,实际是使用synchronize+CAS来操作的。并且synchronized锁在JDK1.7时对锁进行了优化,整个看起来就行优化过且线程安全的HashMap。

3. HashMap为啥每次扩容是原来的2倍

  1. HashMap实行了懒加载,新建HashMap的时候不会对table进行赋值,而是到第一次插入时,进行resize时构建table
  2. 当HashMap.size 大于计算好的阈值 threshold时, 会进行resize;threshold的值,当第一次构建时, 如果没有指定HashMap.table的初始长度, 就用默认值16, 否则就是指定的值; 然后不管是第一次构建还是后续扩容, threshold = table.length * loadFactor;

为什么是2倍扩容?

第一是因为哈希函数的问题,通过除留余数法方法获取桶号,因为哈希表的大小始终为2的n次幂,因此可以将取模为位运算操作,提高效率,容量n为2的幂次方,n-1的二进制会全为1,位运算可以充分散列,避免不必要的哈希冲突,这也就是为什么要按照2倍方式扩容的一个原因

第二是因为是否移位的问题

是否移位,由扩容后表示的最高位是否1为所决定,并且移动的方向只有一个,即向高位移动。因此,可以根据对最高位进行检测的结果来决定是否移位,从而可以优化性能,不用每一个元素都进行移位,因为为0说明刚好在移位完之后的位置,为1说明不是需要移动oldCop,这也是其为什么要按照2倍方式扩容的第二个原因。

4. ConcurrentHashMap的put操作过程

JDK1.7put的实现:

JDK1.7中引入Segment,Segment类通过继承ReentrantLock类,进行加锁,从而控制整个插入过程。

Segment数组也是一种数组加链表的结构方式,每个segment[i]都有一把锁,当某对<key,value>想要进行插入操作,首先要找对应segment数组对应的index,并获取锁,才能对HashEntry进行操作。

第一步:首先通过ConcurrentHashMap中的put方法,计算key.hash的值,根据hash值定位到segment索引;

第二步:进入到segment的put()方法,1.要上锁;2.计算出当前key.hash;3.确定hashEntry的位置,找到此hashEntry[i]的头节点first;3.1 此节点是否是null,若不是则需要遍历,3.2遍历完成或此节点为空,创建HashEntry,插入;3.3此处要注意判断当前segement的count数量,是否需要进行rehash;4 释放锁。

JDK1.8put的实现:

JDK1.8较之前版本进行了改进,采用分段+CAS锁的方式保证线程安全,分段锁是基于synchronized关键字实现的。

1.key或value是否为空,是的话,抛异常new NullPointerException();
2.table是否为空或length0;是的话,初始化table;
3.根据key算出的hash值经过优化得到索引值i,如果i
-1,说明此时有线程扩容此链表,你需要去帮忙扩容。
4.i>=0,则找到table[i]对应的索引,为空的话,就CAS添加;
5.table[i]不为空,取出节点锁住,表示锁住此索引的所有链表或红黑树。判断是key是否重复,重复的话就更新value,否者尾插入法,更新。如果是红黑树就红黑树插入。
6.插入后判断链表的节点数是否大于8,是的话,转换为红黑树,
7.最后判断concurrentHashMap容量,大于扩容值,就进行扩容。
https://blog.csdn.net/tianyuxingxuan/article/details/77434404

5. put里面什么情况下会用CAS,什么情况下用synchronized的机制

6. sleep(0)的作用是什么

指定零 (0) 以指示应挂起此线程以使其他等待线程能够执行。

Thread.Sleep(0) 并非是真的要线程挂起0毫秒,意义在于这次调用Thread.Sleep(0)的当前线程确实的被冻结了一下,让其他线程有机会优先执行。Thread.Sleep(0) 是你的线程暂时放弃cpu,也就是释放一些未用的时间片给其他线程或进程使用,就相当于一个让位动作。

在线程中,调用sleep(0)可以释放cpu时间,让线程马上重新回到就绪队列而非等待队列,sleep(0)释放当前线程所剩余的时间片(如果有剩余的话),这样可以让操作系统切换其他线程来执行,提升效率。

7. mysql默认事务隔离级别

可重复读

四大隔离级别:

未提交读——事务中的修改,即使没有提交,对其他事务也是可见的——脏读、不可重复读、幻读

可重复读——一个事务只能读取到已经提交的事务所做的修改——不可重复读、幻读

提交读——保证一个事务中多次读取同样的数据结果是一样的——幻读

串行化——强制串行化

8. 幻读和不可重复读的区别

幻读:同一事务下,连续执行两次同样的sql语句可能返回不同的结果,第二次的sql语句可能会返回之前不存在的行

不可重复读:同一事物多次读取同一数据集合,读取到数据不一样的情况

9. RR级别会出现幻读吗

会,

10. Mysql如何解决幻读的机制?

解决幻读是采用的Record Lock + Gap Lock解决

11. 说一下MVCC

MVCC,是多版本并发控制,主要为了去提升并发性能的考虑,通过行级锁的变种,避免加锁操作,减少开销,只适用于读已提交和可重复读两个隔离级别。主要是通过读取历史版本数据,来降低并发事务冲突,从而提升并发性能的一种机制。

12. MySQL MVCC具体实现方式是哪一种

13. 说一下TCP四次挥手,越详细越好

14. 为什么是四次挥手,最后一次如果不挥手会有问题吗?

15. 为什么是等待2MSL?为什么不是1MSL

16. Synchronized锁升级过程

synchronized 锁升级原理:在锁对象的对象头里面有一个 threadid 字段,在第一次访问 的时候 threadid 为空,jvm 让其持有偏向锁,并将 threadid 设置为其线程 id,再次进 入的时候会先判断 threadid 是否与其线程 id 一致,如果一致则可以直接使用此对象, 如果不一致,则升级偏向锁为轻量级锁,通过自旋循环一定次数来获取锁,执行一定次数之 后,如果还没有正常获取到要使用的对象,此时就会把锁从轻量级升级为重量级锁,此过程 就构成了 synchronized 锁的升级。

17. 为什么要引入锁的升级机制?

锁的升级的目的:锁升级是为了减低了锁带来的性能消耗。在 Java 6 之后优化 synchronized 的实现方式,使用了偏向锁升级为轻量级锁再升级到重量级锁的方式,从而 减低了锁带来的性能消耗。

18. 偏向锁主要解决什么问题

偏向锁的目标是,减少无竞争且只有一个线程使用锁的情况下,使用轻量级锁产生的性能消耗。

轻量级锁每次申请、释放锁都至少需要一次CAS,但偏向锁只有初始化时需要一次CAS。

19. 偏向锁是怎么加锁的?

偏向锁假定将来只有第一个申请锁的线程会使用锁(不会有任何线程再来申请锁),因此,只需要在Mark Word中CAS记录owner(本质上也是更新,但初始值为空),如果记录成功,则偏向锁获取成功,记录锁状态为偏向锁,以后当前线程等于owner就可以零成本的直接获得锁;否则,说明有其他线程竞争,膨胀为轻量级锁。

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-07-09 17:39:16  更:2021-07-09 17:40:11 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/5 15:53:00-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码