学习笔记9——JUC三种量级的锁机制

学习笔记系列开头惯例发布一些寻亲消息

链接:https://baobeihuijia.com/bbhj/contents/3/197325.html
在这里插入图片描述

  • 多线程访问共享资源冲突

    • 临界区:一段代码块存在对共享资源的多线程读写操作,称这段代码块为临界区

    • 竞态条件:多个线程在临界区内执行,由于代码的执行序列不同导致结果无法预测,称发生了竞态条件

  • 一些线程安全的例子(什么时候加锁什么时候不加):

    • 局部变量是线程安全的(每个线程创建的栈内部独立拥有)
      在这里插入图片描述

    • 局部变量引用的对象:如果用的对象的公共变量,需要加锁,因为对象在堆内
      在这里插入图片描述

    • 局部变量引用的对象:如果用的是对象方法内的局部变量**(虽然这种情况下每个线程在堆内单独拥有对象使用权,但是如果子类重写方法,新加了线程,那么也会出现两个线程共享局部变量的情况,所以尽量用final或者private将父类保护起来)**

    在这里插入图片描述

    • 线程安全类:

      • string:在定义string类的时候,就已经声明了final,所以不会出现子类继承string,并且修改string的读写逻辑为多线程,所以对于单独一个string来说,我们的读写是安全的,因为只有有一个线程进行读写,但是多个方法的组合之间可以插入不同的别的线程,所以不是原子或者说不是安全的。
        在这里插入图片描述
  • 在这里插入图片描述

  • 重量级锁——synchronized【父母考核:我听父母的,父母来决定我的owner,当追求者很多时,采用这种方案】

    • 加锁room,别的线程会进入block,直到本线程释放锁,才会唤醒别的block线程,在这个过程中就算时间片轮完该线程,其他线程也无法唤醒

    • 用对象锁的形式保证了临界区代码的原子性,避免多个线程一起执行同一段临界区代码,如果这个锁没有被用,那么就可以执行这段代码

    • 锁住对象和锁住类对象是不同的,并不互斥(也就是说,在执行锁住对象的时候,当这轮cpu片时间耗尽,cpu也会去执行锁住类对象的操作,类对象锁不会被阻塞)

      # 方法一
      synchronized(对象)# 方法二
      class Room {private int counter = 0;// 等价于 synchronized(this)public synchronized void increment() {counter++;}public synchronized void decrement() {counter--;}public synchronized int getCounter() {return counter;}
      }# 方法三
      class Test{// 等价于synchronized(Test.class)public synchronized static void test(){}
      }
      
    • Monitor

      • 对象头

        • 普通对象:32bit的Mark Word(25位hashcode,每个对象都有自己的哈希码,4位的GC分代,锁状态标志)+32bit的Klass Word(类型指针)
      • 数组对象:32bit mark word + 32bit klass word + 32bit的 数组长度

      外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    • synchronized的原理:

      • 每次线程遇到synchronized(obj),会去检查obj是否指向操作系统中的一个monitor,如果没有指向那就将obj对象的mask word 修改为monitor的地址,并将锁标志位从01改为10,将该线程置为monitor的Owner
      • 在此期间如果别的线程执行遇到synchronized(obj),那么就会索引到monitor,发现已经有别的owner,进入entrylist 变为BLOCKED状态
      • 当前owner执行完成后,随机唤醒一个BLOCKED线程,最后退出该对象时将自己的markword重置为hashcode等

      外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    • 重量级锁的线程自旋优化

      • 为了避免线程阻塞,发生上下文切换,从而自旋等待解锁
      • 适合多核cpu,单核的cpu没有自旋的意义,因为没有额外的cpu可以来执行自旋(需要等你结束我才能执行,但是我还总要中途打扰你问你好了没)
      • 自旋失败:几次自旋重试后还是得不到锁就进行阻塞
  • 轻量级锁(操作系统自动创建,不需要我们显式定义)【私定终生,我来决定我的owner】

    • 加锁:线程中创建一个LOCK RECORD 00表示轻量级锁,与对象头交换mask信息(类似于一种密码机制,只有当前线程完成后,才会把密码信息还给对象,别人来访问交换时这个对象已经是加锁状态)

    • 锁重入:当前线程已经拿到锁了,但是又执行了一遍synchronized(obj),这时会新建一个LOCK RECORD 00栈帧,数据这里会存储null,说明其他栈帧已经拿到锁了

    • 解锁:如果是null,直接清除即可,不是null则需要将mask word恢复给对象

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    • 锁膨胀(追求者很多产生了竞争,发现决定权给到父母后,就需要与父母沟通)

      • 线程加轻量级锁失败,进入锁膨胀流程,变成重量级锁(修改原始密码为monitor地址,owner置为当前线程,后续线程进入阻塞)
      • 原来线程的轻量级锁解锁失败(因为密码匹配不对,对象的密码现在是monitor地址),需要进入重量级锁的解锁流程,即找到monitor对象,将owner置为null,并唤醒阻塞线程

    外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  • 偏向锁(只有一个线程一直重复用偏向——》有别的线程也来用该对象就会撤销变为轻量级锁——》锁之间有竞争交互就用重量级)

    • 原始:将对象的mask word与新建锁栈帧的头部信息交换(锁重入都会尝试交换信息,造成资源浪费)

    • 偏向:将对象的mask word修改为线程ID,锁重入就不会新建锁栈帧

    • 当前线程id释放后,线程id还是不会改变,该对象已经从属于该主线程

    • 外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

    • ban掉偏向锁的方法

      • 当一个可偏向的对象调用了hashcode就会ban掉偏向锁
      • 当对象已经偏向一个线程了,另一个线程也来用该对象,但是不竞争,就会变为轻量级(线程id部分变为锁记录指针),如果竞争交互就是重量级
      • 调用wait,notify也会撤销,因为wait,notify只有重量级有
    • 批量重偏向

      • 超过一定阈值数量(20)的对象都在撤销偏向锁,就会认为偏向设置的线程有误,因此会将所有的对象偏向锁改为别的线程
      • 撤销的性能消耗比较大
      • 批量执行
    • 批量撤销

      • 撤销超过阈值(40)的对象都在撤销偏向锁换轻量级(说的是所有线程的总数),偏向就要求整个类原始对象和新对象不再偏向,直接轻量级
  • JIT即时编译进行逃逸分析

  • sleep和wait的区别(状态都是timewaiting)

    • sleep是线程的方法,执行时不会放弃锁:相当于屋子内的人把门锁死,直到醒来检查一下资源是否满足

    • wait是对象A的方法,会放弃锁,需要notify叫醒:屋子内的人发现缺资源就出来在门外等着A.wait(),等到资源满足执行notify【这种方法可以通过资源的识别需要通过while条件来判断】

      • synchronized(lock){while(资源不满足){lock.wait();}// 干活
        }synchronized(lock){lock.notifyAll()
        }
        

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于jsp+servlet的图书管理系统

基于jspservlet的图书管理系统演示地址为 图书馆后台管理系统 用户名:mr ,密码:123 图书馆管理系统主要的目的是实现图书馆的信息化管理。图书馆的主要业务就是新书的借阅和归还, 因此系统最核心的功能便是实现图书的借阅和归还。此外,还需要提供图书…

如何排查rpc mount export: RPC: Timed out问题

文章目录 问题描述查看nfs服务是否运行正常如果以上都通过,尝试下面步骤 问题描述 我们将讨论您在 NFS 客户端上看到的 NFS 错误之一的故障排除。在尝试与 NFS 相关的命令时可以看到此错误,如下所示: 通常,当您看到此错误时,您也…

两个观察伦敦银关键点位的方法

所谓关键点位,就是伦敦银价格测试了之后容易出现走势转向的位置。例如银价上涨至某些关键点位后出现反转下跌,或者跌到某些关键点位后反转上涨。我们清楚关键点位对交易的重要性之后,就要开始了解怎么找到这些关键点位,下面我们就…

Xilinx FPGA——ISE时序约束“建立时间不满足”问题解决记录

一、现象 最近使用赛灵思的FPGA设计项目时,出现时序约束失效问题。 点进去发现如下: 一个始终约束没有生效,有多处报错。 二、原因 出现这个问题的原因是,建立时间不满足。 时序违例的主要原因是建立时间和保持时间不满足要求&a…

SAP 按比例替代的使用简介

相信很多PP顾问比较头大的问题就是替代料的问题,尤其是电子行业的替代料颇为复杂,本文主要讲解的是SAP系统标准的替代料的使用方式。 第一种:按比例替代 1、创建物料—MM01 成品: 11000001 原材料 31000002 原材料 31000003 原材料 31000004 2、创建BOM—CS01 维护替代…

【Linux】resolv.conf 文件

resolv.conf resolv.conf 文件 是 DNS 的 client 端使用的文件,用于设置 DNS 服务器的 ip 地址以及 DNS 域名,还可以配置域名搜索顺序等等。主要包含如下关键字:nameserver、domain、search、sortlist、options。设置的格式都是 关键字空格 …

3D材质编辑:制作被火烧的木头

在线工具推荐: 3D数字孪生场景编辑器 - GLTF/GLB材质纹理编辑器 - 3D模型在线转换 - Three.js AI自动纹理开发包 - YOLO 虚幻合成数据生成器 - 三维模型预览图生成器 - 3D模型语义搜索引擎 当谈到游戏角色的3D模型风格时,有几种不同的风格&#xf…

openEuler JDK21 部署 Zookeeper 集群

zookeeper-jdk21 操作系统:openEuler JDK:21 主机名IP地址spark01192.168.171.101spark02192.168.171.102spark03192.168.171.103 安装 1. 升级内核和软件 yum -y update2. 安装常用软件 yum -y install gcc gcc-c autoconf automake cmake make \zl…

【ET8】1.ET8入门-运行指南

主要学习网址 论坛地址为:https://et-framework.cn Git地址为:GitHub - egametang/ET: Unity3D Client And C# Server Framework 官方QQ群 : 474643097 项目检出 检出项目切换到release8.0分支 GitHub地址:GitHub - egametang/ET: Unity…

第二十一章,网络通信

网络协议 IP协议 IP是Internet Protocol的简称,是一种网络协议。Internet 网络采用的协议是TCP/IP协议,其全称是Transmission Control Protocol/Internet Protocol。Internet 依靠TCP/IP协议,在全球范围内实现了不同硬件结构、不同操作系统…

存储成本降71%,怪兽充电历史库迁移OceanBase

怪兽充电作为共享充电宝第一股,业务增长迅速,以至于业务架构不停地增加组件。在验证 OceanBase 可以简化架构并带来更大的业务价值后,首次尝试在历史库中使用 OceanBase 替代 MySQL,存储成本降低 71%。本文为怪兽充电运维架构部王…

如何使用eXtplorer+cpolar内网穿透搭建个人云存储实现公网访问

文章目录 1. 前言2. eXtplorer网站搭建2.1 eXtplorer下载和安装2.2 eXtplorer网页测试2.3 cpolar的安装和注册 3.本地网页发布3.1.Cpolar云端设置3.2.Cpolar本地设置 4.公网访问测试5.结语 1. 前言 通过互联网传输文件,是互联网最重要的应用之一,无论是…