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

八股-2025.10.12

1.ConcurrentHashMap 线程安全的具体实现方式。

A.JDK1.7实现:分段锁(Sement锁)

JDK1.7的ConcurrentHashMap采用的是“分段锁”机制,底层结构是“数组(Segment)+数组(HashEntry)+链表”,核心是将整个哈希吧拆为多个独立的“段”,每个段对应一把锁。

实现机制:

锁的粒度:锁仅用于"Segment”级别——线程操作某个“Segment”时,只需获取该Segment“的锁,其他”Segment“不受影响。

并发能力:理论上,ConcurrentHashMap的最大并发数等于Segment数组的长度(默认16),即最多16个线程可同时操作不同Segment,大幅提升吞吐量。

读写优化:

写操作:必须获取Segment锁,确保同一时间只有一个线程修改该Segment的数据

读操作:无需加锁——因为HashEntry的value和next指针用volatile修饰,能保证读操作看到最新值,且Segment内部结构修改时(如扩容),不会影响已存在的HashEntry引用。

B.JDK1.8实现:CAS+synchronized(取消分段锁,细粒度到节点)

JDK1.8彻底放弃了“分段锁”,借鉴HashMap的“数组+链表/红黑树”结构,改用“CAS无锁操作+synchronized“实现线程安全,锁粒度细化到”哈希桶的头节点“,并发性能进一步提升。

实现机制:

put操作:数组未初始化时,多线程通过CAS竞争初始化标记,只有成功线程能完成初始化,其他线程自旋等待;定位哈希桶后,若桶为空则直接用CAS插入新节点,失败则自旋重试;若桶非空则用synchronized锁定同的头结点,确保单线程修改该桶的链表或红黑树,完成key的更新或插入后,若元素超过阈值则触发扩容。

get操作:全程无锁却能确保线程安全,关在在于Node的value和next指针被volatail修饰:根据Java的内存模型,volatail确保写操作的可见性,线程对value和next的修改能被其他线程立即感知;同时,遍历桶内链表或红黑树时,volatail保证不会出现”半修改“的节点引用,使无锁遍历能正确获取数据。

扩容操作:支持多线程协助以提升效率,先通过CAS将sizeCtl设为扩容状态,防止其他线程同时扩容;原数组哈希桶被分为多个片段,个线程负责迁移不同片段到新数组;线程迁移完一个片段后,用CAS更新迁移进度标记,避免其他线程重复迁移;扩容期间,写操作会先协助迁移当前桶再执行插入,读操作则同时检查原数组和新数组,确保能正确获取数据。

https://www.bilibili.com/video/BV1rp4y1P7ci/?spm_id_from=333.337.search-card.all.click&vd_source=3abe3667e67749032f72d6f512b2a967

2.C++ 中堆内存和栈内存的区别?

A.管理方式:

栈内存由编译器自动管理,遵循”先进后出“的原则,当函数调用时,局部变量和函数参数等会被自动压入栈中,函数执行结束后,这些内存会被自动弹出并释放,无需开发者手动干预;而堆内存需要开发者手动申请,和释放,编译器不会自动管理,若忘记释放则会导致内存泄漏。

B.生命周期:

占内存的生命周期与所在的作用域绑定,例如函数内的局部变量,当函数执行完毕胡,栈内存就会被释放,无法在作用域外访问;对内存的生命周期由开发者控制,从new申请开始,到delete释放结束,只要未释放,就可以在多个作用域间共享,但也因此更容易因管理不当导致内存问题。

C.分配效率:

栈内存的分配和释放是连续的,通过移动栈顶指针即可完成,几乎没有额外开销,效率极高;堆内存的分配需要在内存中寻找合适的空闲块,释放时还可能触发合并相邻空闲块的操作,因此效率较低,且频繁分配释放容易产生内存碎片。

D.空间大小:

栈的大小通常是固定的,若分配超过栈的空间,会导致栈溢出;堆内存的大小更灵活,理论上受限于系统的可用内存,适合存储大型数据或动态大小的数据。

E.适用场景:

栈适合存储生命周期短且大小固定的临时数据,如函数参数,局部变量,循环变量等;堆内存适合存储生命周期长,大小动态变化或需要跨作用域共享的数据,如动态数组,大型对象,链表节点等。

https://www.bilibili.com/video/BV1Sepyz7ECL/?spm_id_from=333.337.search-card.all.click&vd_source=3abe3667e67749032f72d6f512b2a967

3.synchronized和Lock有什么区别?(JAVA)

https://www.bilibili.com/video/BV1XS4y1S7W1/?spm_id_from=333.337.search-card.all.click&vd_source=3abe3667e67749032f72d6f512b2a967

4.说说volatile的用法及原理。(JAVA)

https://www.bilibili.com/video/BV19kDgYQEhH/?spm_id_from=333.337.search-card.all.click&vd_source=3abe3667e67749032f72d6f512b2a967

5.联合索引的存储结构与最左前缀原则

A.联合索引的存储结构(InnoDB为例):

InnoDB中联合索引的底层仍基于B+树实现,但和单列索引的区别是:B+树的”索引键“十多列值的组合,而非单一列值。其存储结构有三个特点:

a.所有叶子节点会按照”索引列的定义顺序“排序。这种”先左后右“的排序方式,是”最左匹配原则”的底层基础。

b.和InnoDB的单列二级索引一样,联合索引的叶子节点不存储整行数据,而是存储“主键值”(需要通过主键回表查询完整数据。

c.B+树非叶子节点的索引键存储的是“索引列的组合前缀”,用于引导查询方向。

B.最左前缀原则:联合索引的使用规则

最左前缀原则是指:联合索引只有在查询条件包含“索引最左侧列“,且按索引列顺序排列时,才能生效;若跳过左侧列或打乱顺序,索引会部分失效或完全失效。其本质是”顺应B+树的排序逻辑“,因为B+树按”左侧优先“排序,只有从左列开始匹配,才能利用索引的有序性快速定位;若跳过左列,索引的排序逻辑无法发挥作用,只能走全表扫描。

https://www.bilibili.com/video/BV1894y1i7xE/?spm_id_from=333.337.search-card.all.click&vd_source=3abe3667e67749032f72d6f512b2a967

6.说说线程的创建方式。(JAVA)

https://www.bilibili.com/video/BV1Ru4y1n7Lw/?spm_id_from=333.337.search-card.all.click&vd_source=3abe3667e67749032f72d6f512b2a967

7.Redis中的Zset怎么实现的?(JAVA)

https://www.bilibili.com/video/BV1BG4y197wV/?spm_id_from=333.337.search-card.all.click&vd_source=3abe3667e67749032f72d6f512b2a967

http://www.dtcms.com/a/474590.html

相关文章:

  • Eigen 曲线拟合之四阶多项式(有界约束,投影法)
  • 深度剖析 C++ 之 vector(下)篇
  • Vue计算属性与监视
  • 零基础学AI大模型之解析器PydanticOutputParser
  • Linux 命令 —— 常用命令总结
  • 【AI论文】大型推理模型能从有缺陷的思维中更好地习得对齐能力
  • 网站服务器费用wordpress手赚推广
  • 24ICPC昆明站补题
  • 口碑好的聊城网站建设设计软件网站
  • 五种编程语言比较选择最适合您项目的工具
  • 商城网站开发项目分工公司网页背景图
  • 第六章:并发编程—Go的杀手锏
  • 网站建设内部流程图定制开发网站 推广
  • 衡石科技HENGSHI SENSE 6.0:重塑企业级BI的技术范式
  • 西安便宜网站建设品牌网十大品牌排行榜
  • OpenSIPS call_center 模块测试
  • 深度学习周报(10.6~10.12)
  • 易语言实现多文件选择对话框模块详解
  • 电子商务网站建设与综合实践如何翻译wordpress主题
  • Java基础--集合复习知识点
  • spdlog讲解
  • 怎样用vps做网站超级优化
  • 下载接口返回的数据流格式文件
  • 关于网站建设的合同范本正规太原软件开发公司有哪些
  • Python反射机制通俗详解(新手友好版)
  • 网站开发要源码多少钱wordpress 静态资源加速
  • 【多线程】阻塞等待(Blocking Wait)(以Java为例)
  • 公众号做 视频网站商品行情软件下载
  • Kubernetes环境下Nginx代理Nacos服务请求故障诊断
  • Linux 文件权限详解与实操命令