Synchronized锁

2023-05-16

1、Synchronized基本特性回顾

  应用场景:多线程环境下保证线程的安全性。
  使用方式:
    1)Synchronized加在普通方法上,使用的是this锁,也就是当前对象
    2)Synchronized加在静态方法上,使用的是class字节码作为锁
    3)Synchronized加在代码块,可以以任何对象作为锁
       Synchronized锁会关联一个对象 monitor对象
  Synchronized是一个Java关键字  Java对象 转 C代码 转 汇编。

2、Synchronized monitor对象源码解读

  每个 Java 对象都可以关联一个 Monitor 对象,如果使用 synchronized 给对象上锁(重量级)之后,该对象头的Mark Word 中就被设置指向 Monitor 对象的指针。
        Synchronized的锁对象的对象头中的Mark Word会关联一个monitor对象。这个monitor对象不是我们主动创建的,是JVM的线程执行到这个同步代码块,发现锁对象没有monitor就会创建monitor,monitor内部有两个重要的成员变量:
  【owner】记录拥有这把锁的线程;
  【recursions】记录线程拥有锁的次数(重入次数、递归次数)。
    当一个线程拥有monitor后其他线程只能等待
  【_EntryList】锁池。锁的竞争过程中,一旦有线程抢锁成功,其他线程会存放在_EntryList中,处于等待阻塞状态。竞争锁失败的会存放在这里阻塞等待。
    (当锁释放之后,唤醒锁池中的线程)
  【_cxq】竞争,所有线程都没有拿到锁的情况下,通过单向链表的形式存放参与竞争的线程。一旦有线程抢锁成功,其他线程会存放在_EntryList中。
  【_WaitSet】等待池。等待池中的线程不会去竞争锁资源。通过锁对象的.wait方法,当前线程释放所持的锁,且变为阻塞状态存放到_WaitSet;调用notify方法时,取出一个在_WaitSet中等待的线程,放入到_EntryList中(并未唤醒)。notify方法所谓的唤醒线程只是将线程转移到_EntryList中,并未真正唤醒。

3、Synchronized对象布局分析

对象头16个字节:
  MarkWord     对象自身的运行时数据 :存放hashcode、GC分代、锁状态标记、持有的锁线程、偏向锁线程 ID等  8个字节。  
  Class Point    指向实例的引用                                                    8个字节
实例数据(成员变量 ):
  private int userId;  //4个字节
对齐填充数据:
  由于HotSpot虚拟机的自动内存管理系统要求对象的起始地址必须是8字节的整数倍,也就是对象的大小必须是8字节的整数倍。
  当对象头加上实例数据的字节数不是8的倍数,需要通过对齐填充来补全。

4、new 一个对象占用多少个字节?

  对象头16个字节(未压缩)+实例数据(int四个字节,boolean1个字节)+填充数据(凑8的倍数)。  

5、Synchronized锁的升级过程  

5.1偏向锁:(jdk6开始优化)

  定义:只有一个线程重复使用的时候产生,通过判断减少CAS过程。(适用于一个线程)
  优点:没有锁的竞争,提高锁的效率。
  过程
  ① 线程t1检查Java对象头中是否有关联当前线程。
  ② 如果没有的情况下,使用CAS修改MarkWord,标记为当前线程t1。
  ③ 如果使用CAS修改成功,获取锁;如果修改失败,则说明当前MarkWord已经被其他线程修改过,获取锁失败。
  ④ 如果使用CAS修改MarkWord成功,MarkWord标记为当前线程,同时修改MarkWord中偏向锁标记为1。
  偏向锁撤销:如果线程一直持有偏向锁,突然有另一个线程开始竞争java锁对象,这时偏向锁会开始撤销。撤销之后有可能会改为轻量锁或重量锁。

5.2 轻量锁

  定义:当多个线程在间隔的方式竞争我们的锁对象,短暂结合自旋控制。
  栈帧:方法的执行空间
  过程
  T线程会复制对锁象头中markword(gc分代、hashcode)到栈帧空间,使用CAS修改锁对象的markword(非复制过来的markword)指针关联到该线程的栈帧空间地址,修改成功执行同步代码;修改失败则自旋,自旋多次升级为重量级锁。
  为甚么要升级到重量级锁?    因为自旋非常消耗内存

5.3 重量锁:

  只要有一个线程获取到锁,其他线程都会变为阻塞状态。效率非常低。

6、、偏向锁、轻量级锁、自旋锁、重量级锁过程

  偏向锁:只有一个线程的情况下,可以使用轻量级减少CAS加锁和释放锁的操作。如果多个线程同时访问,偏向锁会撤销为轻量锁或重量锁。
  轻量锁:多个线程间隔或短暂竞争锁的情况下。不会导致当前线程阻塞,没有获取到锁的线程会采用自旋的形式重复获取锁,但是非常消耗内存,如果多次重复获取锁,则升级为重量锁。
    应用场景:同步代码块里的代码执行时间是非常快的情况下。
  重量锁:没有获取到锁的线程会变为阻塞状态,效率是极低。
    应用场景:线程不会采用自旋的形式,不会消耗CPU资源,释放CPU执行权,同步代码块执行可能比较耗时,其他线程在自旋过程中仍未执行完同步代码块。

7、Synchronized锁的使用需要注意哪些优化问题

1)减少Synchronized同步的范围,减少同步代码块执行的时间,只会使用到偏向锁或轻量锁;
2)将锁的粒度拆分得更细;
  类似Conhashmap底层实现原理 降低锁的粒度
3)锁一定要做读写分离,只是读的操作不需要加锁;

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Synchronized锁 的相关文章

  • Synchronized(对象锁)和Static Synchronized(类锁)的区别

    Synchronized和Static Synchronized区别 通过分析这两个用法的分析 我们可以理解java中锁的概念 一个是实例锁 锁在某一个实例对象上 如果该类是单例 那么该锁也具有全局锁的概念 一个是全局锁 该锁针对的是类 无
  • 13张图,带大家深入理解Synchronized

    目录 前言 内容大纲 Synchronized使用方式 普通函数 静态函数 代码块 Synchronized原理 Synchronized优化 锁粗化 锁消除 锁升级 偏向锁 轻量级锁 重量级锁 前言 Java并发编程系列第二篇Synchr
  • java中的final变量和synchronized块

    Java中的final变量是什么 例如 如果我写final int temp 函数中final关键字的含义是什么 另外 我什么时候想使用final变量 既作为类变量又作为函数变量 为什么同步块中的变量必须声明为final Final 变量和
  • 更好的解决方案而不是 Java 中的嵌套同步块?

    我有一个Bank类有一个列表Account 该银行有一个transfer 将价值从一个帐户转移到另一个帐户的方法 这个想法是锁定两个from and to转账内的账户 为了解决这个问题 我有以下代码 请记住 这是一个非常简单的示例 因为它只
  • 在函数中通过类名同步是否在扩展类中有效?

    我在基类中有一个方法 foo 使用 Synchronized 类名 以及扩展基类的两个类 A 和 B 如果我在两个不同的线程中从 A 实例和 B 实例调用 foo 它们会同步吗 这是一个示例代码 class BaseClass void f
  • 我应该使用同步方法来改变该字段吗?

    随着接下来的课程 This class should be thread safe class BankAccount private long balance Should it be volatile synchronized void
  • Java 中使用同步块的并发未给出预期结果

    下面是一个简单的 java 程序 它有一个名为 cnt 的计数器 该计数器会递增 然后添加到名为 monitor 的列表中 cnt 由多个线程递增 值由多个线程添加到 monitor 在方法 go 的末尾 cnt 和 monitor siz
  • 为什么 Thread.interrupt() 不能中断尝试获取锁的线程

    Thinking in Java 一书中写道 Thread interrupt 无法中断尝试获取同步锁的线程 我想知道为什么 阻塞操作只有在声明为抛出异常时才能被中断InterruptedException 显然 一个synchronize
  • 为什么Java构造函数不能同步?

    根据Java语言规范 http java sun com docs books jls third edition html classes html 8 8 3 构造函数不能标记为同步 因为在创建该对象的线程完成之前 其他线程无法看到正在
  • 如何正确使用同步链接哈希图

    尝试通过子类化链接哈希映射来制作 lru 映射 地图通过 collections synchronized 运行 映射的所有用法都被同步块包围 如果它们全部被删除 单元测试也会失败 人们可能会认为它们是不必要的 因为地图是通过 collec
  • 跨 JVM 同步方法

    如何跨 JVM 同步方法 我的示例是一个 Web 应用程序 它限制用户名多次登录 换句话说 第一个用户可以登录 但如果另一个用户使用相同的用户名登录 他就会被拒绝 Web 应用程序部署在多个服务器上 因此存在多个 JVM 并且用户可以尝试使
  • 如果一个同步方法调用另一个非同步方法,该非同步方法是否有锁

    在Java中 如果一个同步方法包含对非同步方法的调用 那么另一个方法是否仍然可以同时访问该非同步方法 基本上我要问的是同步方法中的所有内容都有锁 包括对其他同步方法的调用 如果一个同步方法调用另一个非同步方法 该非同步方法是否有锁 答案取决
  • Java中的多个对象锁?

    锁定私有字段变量 而不是使用锁定对象 是否安全 可接受的做法 这样 我就可以为不同的目的使用不同的锁 下面的例子 class Test private Integer x 0 private Integer y 0 public void
  • 同步块——锁定多个对象

    我正在建模一个游戏 其中多个玩家 线程 同时移动 玩家当前所在位置的信息被存储两次 玩家有一个变量 hostField 它引用棋盘上的一个字段 每个字段都有一个 ArrayList 存储当前位于该字段的玩家 我对拥有冗余信息这一事实不太满意
  • pthread_mutex_t VS @synchronized 块?

    static pthread mutex t gLock global pthread mutex init gLock NULL in init pthread mutex lock gLock for int i 0 i lt mess
  • Java并发中的AbstractQueuedSynchronizer

    What is AbstractQueuedSynchronizer在Java中concurrent locks包用来做什么 有人可以阐明它的方法吗doAcquireInterruptibly and parkAndCheckInterru
  • grails 上的同步块在 Windows 上有效,但在 Linux 上无效

    我有一个 grails 应用程序 它依赖于服务中的同步块 当我在 Windows 上运行它时 同步按预期工作 但当我在 ams linux 上运行时 会出现 StaleObjectStateException 该问题在以下示例中重现 cla
  • 如何使用 wait() 和 notification() 正确暂停线程

    我想要一个启动线程并提供暂停和继续该线程的方法的类 我的第一个方法是使用标志 只要该值为 true 它就会循环 sleep 方法 就像是 public class Bot private Thread t private boolean i
  • 为什么 Volatile 的行为很奇怪

    我最近经历了 volatile 关键字的这种奇怪行为 据我所知 易失性关键字应用于变量以反映对数据所做的更改 变量由一个线程传递到另一个线程 volatile 关键字防止在线程上缓存数据 我做了一个小测试 我使用了一个名为 count 的整
  • 原始类型是易失性的还是同步的?

    在 Java 中 如果变量的大小小于或等于 32 位 则赋值是原子的 但如果变量的大小大于 32 位 则赋值不是原子的 在双重或长分配的情况下 使用什么 易失性 同步 会更有效 Like volatile double x y 同步不适用于

随机推荐

  • LL(1)文法的语法分析java实现

    java代码如下 xff1a package 文法分析器 import java io BufferedReader import java io FileInputStream import java io InputStreamRead
  • CSDN,我的良师益友

    鲁迅曾说过 xff1a 不是缺乏天才 xff0c 而是缺乏培养天才的土壤 对于中国的 IT 行业来说 xff0c 从来不缺乏技术英雄 xff0c 缺少的是铸就技术英雄的平台 而 CSDN 就给了我们这样一个平台和机会 xff0c 所以我们是
  • 构造中小型园区网实训案例

    构造中小型园区网实训案例 一 实验工具与实验拓扑规划1 实验工具2 实验拓扑 二 需求分析三 数据规划四 实施步骤步骤1 xff1a 配置所有终端步骤2 xff1a 配置所有接入层交换机步骤3 xff1a 配置网关路由器AR1 公网路由器A
  • 软件工程复习

    第一章 xff1a 课程概述 1 1 软件危机 1 1 1 计算机软件的四个发展阶段 程序设计阶段 程序系统阶段 软件工程阶段 面向对象阶段 1 1 2 什么是软件危机 xff08 考点 xff09 软件危机是指在计算机软件的开发和维护过程
  • ArrayDeque底层实现

    一 什么是ArrayDeque 1 Deque与Queue 了解这个之前 xff0c 我们要先知道什么是Deque xff0c 它和Queue有什么区别 xff1a 在java中 xff0c Queue被定义成单端队列使用 xff0c De
  • Hive知识点汇总

    HIVE 一 Hive的优化 数据倾斜 xff1a shuffle之后Key的分布不均导致分配到Reduce端的数据不均匀 xff0c 出现个别Reduce的数据过大 xff0c 执行时间过长而出现的现象 1 数据倾斜产生的原因 xff1a
  • CentOS7安装与克隆

    CentOS7安装与克隆 一 新建虚拟机及其配置二 配置虚拟网络编辑器三 安装CentOS 7四 一些工具的安装五 虚拟机克隆六 虚拟机克隆后的配置七 配置ssh免密登陆八 批处理脚本与集群分发脚本1 将家目录配置进环境变量2 批处理脚本3
  • NGINX ./configure详解

    在 34 configure 34 配置中 xff0c with 34 表示启用模块 xff0c 也就是说这些模块在编译时不会自动构建 without 34 表示禁用模块 xff0c 也就是说这些模块在编译时会自动构建 xff0c 若你想N
  • Linux下Nginx安装使用

    一 下载解压nginx span class token comment 进入要放安装包的目录 span span class token builtin class name cd span opt software span class
  • java Collections类 详解

    目录 一 前言 二 Collections类简介 三 Collections类常用方法演示 1 static void reverse List list 代码演示 2 static void shuffle List list 代码演示
  • Activity onNewIntent注意事项

    数据上报发现 xff0c onNewIntent 以后 xff0c onResume和onPause可能不会执行 xff0c 直接执行onStop
  • Python+OpenCV实用案例应用教程:人脸检测和识别

    计算机视觉使很多任务成为现实 xff0c 其中两项任务就是人脸检测 xff08 在图像中定位人脸 xff09 和人脸识别 xff08 将人脸识别为特定的人 xff09 OpenCV实现了一些人脸检测和识别的算法 从安全到娱乐 xff0c 这
  • 基数排序 详细讲解

    1 基数排序 桶排序 介绍 基数排序 xff08 radix sort xff09 属于 分配式排序 xff08 distribution sort xff09 xff0c 又称 桶子法 xff08 bucket sort xff09 或b
  • CentOS7安装docker后服务启动不了

    问题排查 运行yum install docker后 xff0c 安装完成docker 运行 docker info 命令测试docker是否正常 则提示以下错误 xff1a Cannot connect to the Docker dae
  • Linux命令+shell脚本大全:处理损坏的包依赖关系

    有时在安装多个软件包时 xff0c 某个包的软件依赖关系可能会被另一个包的安装覆盖掉 这叫作 损坏的包依赖关系 xff08 broken dependency xff09 如果系统出现了这个问题 xff0c 先试试下面的命令 xff1a y
  • 世界上最简单的无锁哈希表

    英文原文 xff1a preshing xff0c 感谢 64 浅水清流 的热心翻译 如果其他朋友也有不错的原创或译文 xff0c 可以尝试推荐给伯乐在线 以下是译文 无锁哈希表 xff08 Lock Free Hash Table xff
  • nginx ssl及http自动跳转到https配置

    1 Nginx路径配置 如下请求地址 http x x x x 8080 api base test 此时 zo java这个应用接收到的地址是 xff1a http x x x x 8080 api base test location
  • 视图绑定.

    在大多数情况下 xff0c 视图绑定会替代 findViewById 视图绑定功能可按模块启用 要在某个模块中启用视图绑定 xff0c 请将 viewBinding 元素添加到其 build gradle 文件中 xff0c 如下例所示 x
  • 优秀程序员的故事

    A君默默的工作了3年 xff0c 从项目初立 xff0c 到遍地开花 工作不忙 xff0c 工资没长 新领导来了 xff0c 下个版本重新开发 xff0c A君继续维护老版本 新招了一批人 xff0c 加班加点干了半年多 直到版本发布 xf
  • Synchronized锁

    1 Synchronized基本特性回顾 应用场景 xff1a 多线程环境下保证线程的安全性 使用方式 xff1a 1 xff09 Synchronized加在普通方法上 xff0c 使用的是this锁 xff0c 也就是当前对象 2 xf