首页 > 编程语言 >Java中的synchronized

Java中的synchronized

时间:2024-03-16 22:02:17浏览次数:40  
标签:Word synchronized 对象 线程 Java 重量级 轻量级

概述

Java的锁可以分为乐观锁和悲观锁两类。而synchronized是悲观锁的代表。本文想要说明一下两个问题:

synchronized锁的是哪个对象

public void method(){
	synchronized(this){
		...
	}
}
public synchronized void  method(){
	...
}

    上述两种方式,synchronized锁的其实是this对象。

public static void method(){
	synchronized(this){
		...
	}
}
public synchronized static void  method(){
	...
}

    上述两种方式锁的其实是类对象。类对象是啥呢?通过类名.class获得到的对象或者通过Class.forName()得到的对象就是类对象。

怎么判断锁对象被某个线程占用呢

    要了解锁对象被哪个线程所占用,就先要了解对象的内存结构,有三个部分,分别对象头,实例数据和对齐填充。
在这里插入图片描述
注:图片来源于: https://www.bilibili.com/video/BV1PJ411n7xZ?p=105&vd_source=3b276afc1d517ec28a00ae341f72050c

重量级锁

    synchronized中存在锁升级优化,存在线程竞争锁对象时,synchronized会经过偏向锁-轻量级锁-重量级锁的优化过程。本文首先重量级锁为例,说明如何判断锁对象被哪个线程实例所占有。
    正常对象的对象头中存在如下图所示,如果是普通对象,对象头中含有Mard Word和指向方法区中存储的对应的类信息。
如果是数组对象则多了一个数组长度信息。
在这里插入图片描述注:图片来源于: https://www.bilibili.com/video/BV16J411h7Rd?p=75&vd_source=3b276afc1d517ec28a00ae341f72050c
    正常情况下,锁对象中包含有对象的hash码,age表示在分代年龄,超过15,就会从新生代晋升到老年代。biased_lock就是判断synchronized是否为偏向锁,01表示锁的状态,即是偏向锁,轻量级锁还是重量级锁。
在这里插入图片描述
    synchronized在重量级锁的情况下,会关联一个Monitor对象,这个对象中包含等待队列,阻塞队列和Owner三个信息。没有拿到锁的对象就在等待队列中。拿到锁,但是调用了wait方法后,对应线程就会进入阻塞队列,等待其他线程调用notify方法唤醒。
    如果某个线程获取到该锁对象,会将锁对象中的Mark Word的信息替换为Monitor的地址,用30个bit表示,锁中表示锁的状态从01变为了10,10即表示该锁为重量级锁。
在这里插入图片描述    同样的道理,线程在获取轻量级锁和偏向锁时,都会对锁对象的对象头中的Mard Word进行修改,但是原理略有不同。

轻量级锁

    轻量级锁不在关联Monitor的对象,而是在线程内部创建了一个锁记录,如下图Lock Record所示,对象头中Mark Word中的会与锁记录的地址信息进行替换,这个过程是一个原子操作。如果线程释放锁,则会将替换的信息重新交换回来。
在这里插入图片描述
    轻量级锁中,锁对象中Mark Word中的信息经过交换后的结果如下图所示,其中30bit表示线程中的锁记录地址,而后两位00表示锁的状态,即轻量级锁,如果状态码为10则表示重量级锁。
在这里插入图片描述

偏向锁

    偏向锁的实现更加暴力,直接就将Mard Word中的信息修改为Thread的id。如下图所示,Mard Word前23bit用来记录线程的id信息,可以看到锁的状态为01和锁对象初始状态相同,但是可以看到biased_lock从0变为了1,表示为偏向锁。
在这里插入图片描述

三种锁的存在时机

    如果仅有一个线程,synchronized为偏向锁;如果有多个线程,但是在不同时段使用,synchronized为轻量级锁;如果在同一时刻,有多个线程都想获取锁,synchronized为重量级锁。

标签:Word,synchronized,对象,线程,Java,重量级,轻量级
From: https://blog.csdn.net/qq_43552690/article/details/136716216

相关文章

  • JavaScript学习 第三天
    一、数组(一)数组基本知识声明按顺序保存数据的数据类型<body><script>letarr=[1,2,'猪儿',true]</script></body>声明数组函数<body><script>letarr=newArray(1,2,'猪儿',true)</script></body>......
  • JavaScript学习 第一天
    一、什么是JavaScript(一)介绍是一种运行在浏览器的编程语言,进行人机交互(二)可以做什么可以做网页特效,表单验证,进行数据交互,还有服务端编程node.js(三)组成由ECMAScript和WebAPIs组成其中WebAPIs由DOM和BOM组成ECMAScript:js基础语法知识WebAPIs:DOM:操作文......
  • 简单对比Java、Python、Go、Rust等常见语言计算斐波拉契数的性能
    前言最近简单学了下Rust,以我这种菜鸟水平,没感受到什么安全、性能什么方面的优势,只觉得概念太多,编译各种报错。暂时也写不出来什么玩法,索性对比下各种学过的语言的性能。部分语言很早之前学过,很久不用就忘了,所以是用GPT写的。但运行逻辑很简单,所以应该没什么影响。具体的代码可以......
  • 分享一下自己总结的7万多字java面试笔记和一些面试视频,简历啥的,已大厂上岸
    分享一下自己总结的7万多字java面试笔记和一些面试视频,简历啥的,已大厂上岸总结的面试资料:面试资料SSMSSM搭建的版本有很多,例如有一个版本可以这么搭建,两个核心配置文件web.xml,applicationContext.xml。1.前端控制器DispatcherServlet2.过滤器CharacterEncodingFilter`......
  • java基础 韩顺平老师的 面向对象(中级) 自己记的部分笔记
       272,包基本介绍包的三大作用1,区分相同的类  2,当类很多时,可以很好的管理类  3,控制访问范围包基本用法packagecom.hspedu;说明:1,package关键字,表示打包  2,com.hspedu,表示包名包的本质分析(原理)包的本质实际上就是创建不同的文件夹/目录来保存类......
  • Java常用修饰符及示例
    Java修饰符是用来改变类、方法、变量、接口等元素的行为和可见性的关键字。Java修饰符主要分为两大类:访问修饰符和非访问修饰符。访问修饰符(AccessModifiers):public:提供最大的访问权限,任何类(无论是同一包内的还是不同包的)都可以访问到public修饰的类、方法和变量。示例......
  • 【Java】List, Set, Queue, Map 区别?
    目录List,Set,Queue,Map区别?Collection和CollectionsListArrayList和Array区别?ArrayList与LinkedList区别?ArrayList能添加null吗?ArrayList插入和删除时间复杂度?LinkedList插入和删除时间复杂度?LinkedList为什么不能实现RandomAccess接口?SetComparabl......
  • java集合框架——Collection集合概述
    前言之前学过ArrayList,现在接触到更多集合了。整理下笔记,打好基础,daydayup! 集合体系结构集合分为单列结合和双列结合,Collection代表单列集合,每个元素只包含一个值。Map代表双列集合,每个元素包含两个值。(本篇主要说明Collection集合) Collection集合Collection集合......
  • java集合框架——List集合概述及ArrayList,LinkedList的区别
    前言:List系列集合是Collection集合中两个系列的其中一个,整理下笔记。打好基础,daydayup!需要了解Collection的,可以看这篇java集合框架——Collection集合概述  List系列集合List系列集合的特点为添加的元素有序,可重复,有索引。在继承了Collection方法的基础上,有很多索引......
  • 【Java设计模式】二十二、备忘录模式
    文章目录1、备忘录模式2、案例:游戏角色属性数值恢复2.1白箱备忘录模式2.2黑箱备忘录模式3、总结1、备忘录模式一种状态恢复机制,以便可以回到之前的某一个特定状态。如Word的撤销操作、下棋时的悔棋等。又叫快照模式,在不破坏封装性的前提下,捕获一个对象的内部状......