多线程相关(4)

news2024/9/23 9:24:58

线程安全-下

  • 使用层面锁优化
    • 减少锁的时间:
    • 减少锁的粒度:
    • 锁粗化:
    • 使用读写锁:
    • 使用CAS:
  • 系统层面锁优化
    • 自适应自旋锁
    • 锁消除
    • 锁升级
      • 偏向锁
      • 轻量级锁
      • 重量级锁
  • ThreadLocal原理
    • ThreadLocal简介
    • 原理
    • ThreadLocal内存泄漏
  • HashMap线程安全
    • 死循环造成 CPU 100%
  • String不可变原因

使用层面锁优化

减少锁的时间:

不需要同步执行的代码,能不放在同步快里面执行就不要放在同步快内,可以让锁尽快释放。

减少锁的粒度:

它的思想是将物理上的一个锁,拆成逻辑上的多个锁,增加并行度,从而降低锁竞争。它的思想也是用空间来换时间;java中很多数据结构都是采用这种方法提高并发操作的效率,比如:ConcurrentHashMap。
java中的ConcurrentHashMap在jdk1.8之前的版本,使用一个Segment 数组:Segment< K,V >[] segments。
Segment 继承自ReenTrantLock,所以每个Segment是个可重入锁,每个Segment 有一个HashEntry< K,V >数组用来存放数据,put操作时,先确定往哪个Segment放数据,只需要锁定这个Segment,执行put,其它的Segment不会被锁定;所以数组中有多少个Segment就允许同一时刻多少个线程存放数据,这样增加了并发能力。

锁粗化:

大部分情况下我们是要让锁的粒度最小化,锁的粗化则是要增大锁的粒度;
假如有一个循环,循环内的操作需要加锁,我们应该把锁放到循环外面,否则每次进出循环,都进出一次临界区,效率是非常差的。

使用读写锁:

ReentrantReadWriteLock 是一个读写锁,读操作加读锁,可并发读,写操作使用写锁,只能单线程写。

使用CAS:

如果需要同步的操作执行速度非常快,并且线程竞争并不激烈,这时候使用cas效率会更高,因为加锁会导致线程的上下文切换,如果上下文切换的耗时比同步操作本身更耗时,且线程对资源的竞争不激烈,使用volatile + cas操作会是非常高效的选择。

系统层面锁优化

自适应自旋锁

自旋锁可以避免等待竞争锁进入阻塞挂起状态被唤醒造成的内核态和用户态之间的切换的损耗,它们只需要等一等(自旋),但是如果锁被其他线程长时间占用,一直不释放CPU,死等会带来更多的性能开销;自旋次数默认值是10。
对上面自旋锁优化方式的进一步优化,它的自旋的次数不再固定,其自旋的次数由前一次在同一个锁上的自旋时间及锁的拥有者的状态来决定,这就解决了自旋锁带来的缺点。

锁消除

锁削除是指虚拟机即时编译器在运行时,对一些代码上要求同步,但是被检测到不可能存在共享数据竞争的锁进行削除。Netty中无锁化设计pipeline中channelhandler会进行锁消除的优化。

锁升级

偏向锁

如果线程已经占有这个锁,当他在次试图去获取这个锁的时候,他会已最快的方式去拿到这个锁,而不需要在进行一些 monitor 操作,因为在大部分情况下是没有竞争的,所以使用偏向锁是可以提高性能的

轻量级锁

竞争不激烈的情况下,通过CAS避免线程上下文切换,可以显著的提高性能

重量级锁

重量级锁的加锁、解锁过程造成的损耗是固定的,重量级锁适合于竞争激烈、高并发、同步块执行时间长的情况

ThreadLocal原理

ThreadLocal简介

通常情况下,我们创建的变量是可以被任何⼀个线程访问并修改的。如果想实现每⼀个线程都有⾃⼰的专属本地变量该如何解决呢?JDK中提供的 ThreadLocal 类正是为了解决这样的问题。类似操作系统中的TLAB

原理

首先 ThreadLocal 是一个泛型类,保证可以接受任何类型的对象。
因为一个线程内可以存在多个 ThreadLocal 对象,所以其实是 ThreadLocal 内部维护了一个 Map ,是 ThreadLocal 实现的一个叫做 ThreadLocalMap 的静态内部类。
最终的变量是放在了当前线程的 ThreadLocalMap 中,并不是存在 ThreadLocal 上,ThreadLocal 可以理解为只是 ThreadLocalMap 的封装,传递了变量值
我们使用的 get()、set() 方法其实都是调用了这个ThreadLocalMap类对应的 get()、set() 方法。

例如:
1.存储用户会话

private static final ThreadLocal threadSession = new ThreadLocal();

2.解决线程安全问题

private static ThreadLocal<SimpleDateFormat> format1 = new ThreadLocal<SimpleDateFormat>();

ThreadLocal内存泄漏

实际上 ThreadLocalMap 中使用的 key 为 ThreadLocal 的弱引用,⽽ value 是强引⽤
弱引用的特点是,如果这个对象持有弱引用,那么在下一次垃圾回收的时候必然会被清理掉。
所以如果 ThreadLocal 没有被外部强引用的情况下,在垃圾回收的时候会被清理掉的,这样一来 ThreadLocalMap中使用这个 ThreadLocal 的 key 也会被清理掉。但是,value 是强引用,不会被清理,这样一来就会出现 key 为 null 的 value。假如我们不做任何措施的话,value 永远⽆法被GC 回收,如果线程长时间不被销毁,可能会产⽣内存泄露
ThreadLocal
ThreadLocalMap实现中已经考虑了这种情况,在调用 set()、get()、remove() 方法的时候,会清理掉 key 为 null 的记录。
如果说会出现内存泄漏,那只有在出现了 key 为 null 的记录后,没有手动调用 remove() 方法,并且之后也不再调用 get()、set()、remove() 方法的情况下
因此使⽤完ThreadLocal ⽅法后,最好⼿动调⽤ remove() ⽅法

HashMap线程安全

死循环造成 CPU 100%

HashMap 有可能会发生死循环并且造成 CPU 100% ,这种情况发生最主要的原因就是在扩容的时候,也就是内部新建新的 HashMap 的时候,扩容的逻辑会反转散列桶中的节点顺序,当有多个线程同时进行扩容的时候,由于 HashMap 并非线程安全的,所以如果两个线程同时反转的话,便可能形成一个循环,并且这种循环是链表的循环,相当于 A 节点指向 B 节点,B 节点又指回到 A 节点,这样一来,在下一次想要获取该 key 所对应的 value 的时候,便会在遍历链表的时候发生永远无法遍历结束的情况,也就发生 CPU 100% 的情况。
所以综上所述,HashMap 是线程不安全的,在多线程使用场景中推荐使用线程安全同时性能比较好的 ConcurrentHashMap。

String不可变原因

  1. 可以使用字符串常量池,多次创建同样的字符串会指向同一个内存地址;
  2. 可以很方便地用作 HashMap 的 key。通常建议把不可变对象作为 HashMap的 key;
  3. hashCode生成后就不会改变,使用时无需重新计算;
  4. 线程安全,因为具备不变性的对象一定是线程安全的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1467992.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

15-36V降压充电光伏MPPT充电方案

1.MPPT原理--简介 MPPT&#xff0c;全称为Maximum Power Point Tracking&#xff0c;即最大功点跟踪&#xff0c;它是一种通过调节电气模块的工作状态&#xff0c;使光伏板能够输出更多电能的电气系统能够将太阳能电池板发出的直流电有效地贮存在蓄电池中&#xff0c;可有效地…

【Langchain多Agent实践】一个有推销功能的旅游聊天机器人

【LangchainStreamlit】旅游聊天机器人_langchain streamlit-CSDN博客 视频讲解地址&#xff1a;【Langchain Agent】带推销功能的旅游聊天机器人_哔哩哔哩_bilibili 体验地址&#xff1a; http://101.33.225.241:8503/ github地址&#xff1a;GitHub - jerry1900/langcha…

从软硬件以及常见框架思考高并发设计

目录 文章简介 扩展方式 横向扩展 纵向扩展 站在软件的层面上看 站在硬件的层面上看 站在经典的单机服务框架上看 性能提升的思考方向 可用性提升的思考方向 扩展性提升的思考方向 文章简介 先从整体&#xff0c;体系认识&#xff0c;理解高并发的策略&#xff0c;方…

xff注入 [CISCN2019 华东南赛区]Web111

打开题目 看见smarty 想到模板注入 又看见ip 想到xff注入 一般情况下输入{$smarty.version}就可以看到返回的smarty的版本号。该题目的Smarty版本是3.1.30 在Smarty3的官方手册里有以下描述: Smarty已经废弃{php}标签&#xff0c;强烈建议不要使用。在Smarty 3.1&#xff…

vue实现递归组件

父组件&#xff1a; <Tree :data"data"></Tree> import Tree from "/components/Tree.vue"; const data reactive([{name: "1",checked: true,children: [{name: "1-1",checked: false,},],},&#xff09; 子组件&#…

电脑闹钟软件哪个好用?

电脑闹钟软件哪个好用&#xff1f;一款带有闹钟定时提醒的备忘录软件是比较实用的&#xff0c;很多上班族每天都要处理堆积如山的工作&#xff0c;总是会忙于一件事的时候忘记另外一件事&#xff0c;导致效率极低。如当一项重要会议需要提前准备资料时&#xff0c;我们却忙于其…

【大厂AI课学习笔记NO.51】2.3深度学习开发任务实例(4)计算机视觉实际应用的特点

今天考试通过腾讯云人工智能从业者TCA级别的认证了&#xff01; 还是很开心的&#xff0c;也看不到什么更好的方向&#xff0c;把一切能利用的时间用来学习&#xff0c;总是对的。 我把自己考试通过的学习笔记&#xff0c;都分享到这里了&#xff0c;另外还有一个比较全的思维…

Java 模糊查询不用like,还可以用什么实现

在电商项目中&#xff0c;如果模糊查询用like的话&#xff0c;会给服务器带来很大的压力&#xff0c;导致服务器崩溃这都是有可能的&#xff0c;最开始做电商搜索框的时候&#xff0c;告诉我不可以用like&#xff0c;这对我来说&#xff0c;简直就是在为难我啊&#xff0c;可能…

Opencv实战(2)绘图与图像操作

Opencv实战(2)绘图与图像操作 指路前文&#xff1a;Opencv实战(1)读取与像素操作 三、基本绘图 文章目录 Opencv实战(2)绘图与图像操作三、基本绘图(1).line(2).rectangle(3).circle 四、图像处理(1).颜色空间1.意义2.cvtColor()3.inRange()4.适应光线 (2).形态操作1.腐蚀2.膨…

[VulnHub靶机渗透] FourandSix2.01

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【Java】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收藏 …

解决RabbitMQ管理页面异常/不正确的问题

正确的页面&#xff1a;有Channels、Exchanges等 异常/不正确的页面&#xff1a; 问题原因 我的RabbitMQ是用docker安装的&#xff0c;应该不会是安装的环境有问题。 而且MQ的服务确实是启动了&#xff0c;后端能正常使用&#xff0c;并且管理界面的登录页面也是能正常登录的&…

【软件测试】定位前后端bug总结+Web/APP测试分析

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、Web测试中简单…

【蓝桥备赛】字串简写

字串简写 数据范围 字符串的长度为5*10的五次方&#xff0c;on方时间复杂度会很大。 才用动态规划的思想&#xff0c;dp[i]以i开头的的可能性&#xff0c;因为长度必须大于等于k&#xff0c;当i小于k的时候&#xff0c;如果等于第一个字符&#xff0c;s1时&#xff0c;dp[…

中兴通讯携吉林移动迈向5G-A新阶段,完成3CC技术应用

日前&#xff0c;中兴通讯携手中国移动吉林移动分公司&#xff0c;在5G-A领域取得新突破。具体来说&#xff0c;双方基于MTK芯片M80终端&#xff0c;完成了5G-A三载波聚合试点&#xff0c;实测下行速率达到理论峰值4.25Gbps&#xff0c;相比2.6G单载波速率提升2.5倍。如此成绩&…

C++多继承之菱形继承原理及解决方法

目录 1.单继承和多继承 2.菱形继承 3.虚继承解决菱形继承 3.1使用方法 3.2虚继承原理 4.继承和组合 1.单继承和多继承 一个子类只有一个父类称为单继承 一个子类有多个父类称为多继承 2.菱形继承 菱形继承是多继承的一种复杂的情况 这里会出现一个问题&#xff0c;Assi…

Axtue使用笔记

1、有三种方式可以设置元件顺序 第一种是鼠标右键点击顺序&#xff0c;选择调整操作置顶、置底、上移一层、下移一层&#xff1b; 第二种是在顶部工具栏中&#xff0c;选择调整操作置顶、置底、上移一层、下移一层; 第三种是使用快捷键操作 Windows&#xff1a;置顶&#xff1a…

持续集成,持续交付和持续部署的概念,以及GitLab CI / CD的介绍

引言&#xff1a;上一期我们部署好了gitlab极狐网页版&#xff0c;今天我们介绍一下GitLabCI / CD 目录 一、为什么要 CI / CD 方法 1、持续集成 2、持续交付 3、持续部署 二、GitLab CI / CD简介 三、GitLab CI / CD 的工作原理 4、基本CI / CD工作流程 5、首次设置 …

如何在Python中创建动态图形?

动态图形是使可视化更具吸引力和用户吸引力的好方法。它帮助我们以有意义的方式展示数据可视化。Python帮助我们使用现有强大的Python库创建动态图形可视化。Matplotlib是一个非常流行的数据可视化库&#xff0c;通常用于数据的图形表示&#xff0c;也用于使用内置函数的动态图…

springboot212球队训练信息管理系统

球队训练信息管理系统设计与实现 摘 要 传统办法管理信息首先需要花费的时间比较多&#xff0c;其次数据出错率比较高&#xff0c;而且对错误的数据进行更改也比较困难&#xff0c;最后&#xff0c;检索数据费事费力。因此&#xff0c;在计算机上安装球队训练信息管理系统软件…

Bert-VITS-2 效果挺好的声音克隆工具

持中日英三语训练和推理。内置干声分离&#xff0c;切割和标注工具&#xff0c;开箱即用。请点下载量右边的符号查看镜像所对应的具体版本号。 教程地址&#xff1a; sjj​​​​​​​CodeWithGPU | 能复现才是好算法CodeWithGPU | GitHub AI算法复现社区&#xff0c;能复现…