JUC —— Synchronized 的理解与使用

news/2024/5/20 9:11:36 标签: java, 开发语言, 后端, juc

Synchronized 的理解与使用

java">package com.pengshi.ThreadSychronized;

import org.openjdk.jol.info.ClassLayout;

/**
 * @description: synchronized 的理解
 * 		synchronized 实现原理是对象
 * 		对象 的 组成 :1. 对象头 —— 类的属性
 * 					  2. 实例变量 —— 类中的数据
 * 					  3. 数据对齐 —— 为的是 以 8B 倍数对齐
 *
 * 		com.pengshi.ThreadSychronized.test object internals:
 * 		OFF  SZ      TYPE DESCRIPTION               VALUE
 * 		  0   8           (object header: mark)     0x0000000000000005 (biasable; age: 0)  	// 对象头 64位计算机下 占位 8 B
 * 		  8   4           (object header: class)    0x00067450 								// 类的元数据信息,也就是类模板信息
 * 		 12   1   boolean test.b                    true									// 实例数据
 * 		 13   3           (object alignment gap)											// 对齐补充
 * 		Instance size: 16 bytes
 * 		Space losses: 0 bytes internal + 3 bytes external = 3 bytes total
 * 		这个对象头格式 是 公共格式 , Java对象 和 JVM 对象通用
 *
 *
 *
 * @projectName: Algorithm
 * @see: com.pengshi.ThreadSychronized
 * @author: pc
 * @createTime: 2022/2/26 17:06
 * @version: 1.0
 */


class test1 {
	boolean b = true;
}
public class synchronizedTest {
	public static void main(String[] args) {
		test1 t = new test1();
		test t1 = new test();
		System.out.println(Integer.toHexString(t.hashCode()));
		// 查看 对象头 信息 注意大小端存储的特性
		System.out.println(ClassLayout.parseInstance(t).toPrintable());
		System.out.println(ClassLayout.parseInstance(t1).toPrintable());
	}
}
  • 底层 Monitor 对象 是一种重量级锁

image-20220226182052458

  • _recursions重入锁概念
  • monitor 对象
  • owner 正在运行线程
  • waitSet 调用阻塞线程的方法wait的集合
  • _cxq 竞争的等待队列
  • _EntryList

锁的获取

  1. 通过CAS 尝试 把 monitor 的owner 字段设置为当前线程
  2. 设置之前的owner指向当前线程,说明当前线程再次进入monitor,即重入锁,将 _recursions ++ ,记录重入次数
  3. 如果第一次进入,设置 _recursions = 1,owner为当前线程,并且返回
  4. 获取锁失败,等待锁的释放进行自旋,自旋过程中不断 请求获取锁的操作,同时包装成为node放入_cxq中

Synchronized 优化

无锁 ——> 偏向锁 ——> 轻量级锁 ——> 重量级锁

  • 轻量级锁 就是 线程交替进行运行,没有竞争的条件
  • 重量级锁就是上面monitor的实现

CAS 比较并且交换

  • 其实就是通过比较 发现数据不同时候 ,进行交换 处理
  • Atomic 的原理 就是 CAS
  • CAS 主要是用在 JMM 模型中的 主存数据不一致的问题 多线程模型要进行 副本内存进行存储
  • 所以 线程 实现的过程中 使用CAS 不断 对于主存中数据进行比较,调用,同步自己副本数据
  • 在调用 副本数据 过程中 ,可能导致 线程干预,导致 副本数据 和 主存 数据不一致
  • 所以 使用CAS 比较并且交换 进行设计 通过 不断获取主存数据 在 和 副本数据 比较,相同时候,在进行操作

偏向锁 (代码块中有锁的使用)

认为 只有 某一个线程 进行 锁的获取,适用于一个线程

  • 线程第一次进入时候,把对象头设置成 线程id 、修改状态

  • 一旦有两个线程 获取时候 ,就会撤销偏向锁

  • 暂停拥有的偏向锁的线程,判断对象是否处于被锁定状态

Java 开始启动时候 会很慢 ,所以添加参数 加快启动时间XX:BiasedLockStartupDelay=0

关闭偏向锁 XX:UserBiasedLocking=false

轻量级锁

偏向锁 的升级 —— 轻量级锁

  • 在线程栈帧 里面 创建一个 LockRecord存储对象头 Mark Word,存储指针

自旋锁

就是竞争锁的 时候 ,轻量级锁要 变为 重量级锁,但是还要挣扎一下,所以就有自旋锁出现

  • 避免 线程切换的消耗,

  • 也就是线程 不阻塞 ,不断循环尝试获取锁

  • 默认自旋数量是 10 次

    自适应自旋锁

    自适应 修改 自选数量

锁消除

通过 即时性编译器 (JIT) 进行判断同步代码块的 逃逸分析 ,堆上的所有数据不会逃逸出去 被其他线程访问,不会进行加锁。

锁粗化

对于代码块 频繁加锁的代码,JVM 自己探测到 细小操作 可以加一次锁,进行锁的范围进行放大


http://www.niftyadmin.cn/n/1614826.html

相关文章

16位科技名人一句话辩Android Vs. iPhone

如果组织科技专家、企业家和CEO来一场关于Android Vs. iPhone的辩论赛,其激烈程度肯定丝毫不会亚于关于医保或经济的政治辩论。 智能手机已成为我们生活密不可分的一部分,其重要程度远超过所有配件饰物。事实上,很多用户都是带着他们的爱机入…

关于创业,最成功的idea,初期大多找不到投资人

到底「创新」还是「抄袭」,容易成功? 创业或做大事,创业家就是喜欢「创新」,也认同创新的力量,但你仔细看,当一个创业家有了初次的成功,他再来创业第二次、第三次,他做的东西&#x…

2022/3/7 面试补充

2022/3/7 面试补充 静态方法能够被继承吗? 忘记了,但是知道不能够被继承,但是是什么原因呢?子类不能重写父类的静态方法。因为静态方法加载后是对于父类而言的,子类后面加载,动态加载的过程中,…

Cliqz:最具创新的信息发现阅读应用

Cliqz是最近推出的一款iPhone和iPad应用。相比单纯依靠人工编辑或无灵魂的算法发现最具价值的内容,Cliqz采用的是一种“混合方法”,通过分析联系人和社交网络的动向,第一时间发现新鲜有趣的新闻资讯。 社交媒体是Cliqz的主要信息来源渠道。通…

2022/3/8 面试自我 总结

2022/3/8 面试自我 总结 final 的 修饰 final 修饰类中的属性 表示该属性一旦被初始化便不可改变,这里不可改变的意思对基本类型来说是其值不可变,而对对象属性来说其引用不可再变。其初始化可以在两个地方:一是其定义处,也就是…

苹果禁售三星产品诉讼被全面驳回,过程很讽刺

来自Reuters的消息,美国联邦法官Lucy Koh驳回了苹果要求禁止三星Galaxy系列智能手机及平板电脑在美国销售的申请。本次诉讼中,苹果试图阻止三星在专利争端期间在其最大市场进行产品销售。 这次的申请只是苹果对三星产品禁售的开端,不过判定结…

对于 springMVC 接受 对象数组 的json 数据

对于 springMVC 接受 对象数组 的json 数据 将前端数组对象 转为字符串 进行 处理 this.$http({url: this.$http.adornUrl(/menu/step/save?${this.dishId}),method: "post",data: this.$http.adornData({steps: JSON.stringify(this.stepList)})}).then(({ data …

要怨就怨运营商,别TM就知道喷Carrier IQ

本周Carrier IQ的“窃听风云”可谓闹得沸沸扬扬,被预装于成千上万的智能手机中,窃听用户的私密信息,要不是25岁的黑客发现并将证据制成视频公诸于众,还不知有多少用户数据被盗用。 而此新闻一出,人们诚惶诚恐&#xff…