返回顶部
首页 > 资讯 > 后端开发 > Python >JAVAsynchronized原理详解
  • 826
分享到

JAVAsynchronized原理详解

2024-04-02 19:04:59 826人浏览 安东尼

Python 官方文档:入门教程 => 点击学习

摘要

目录1、synchronized的作用2、synchronized的语法3、Monitor原理4、synchronized的原理4.1偏向锁4.2轻量级锁4.3锁膨胀4.4重量级锁4

1、synchronized的作用

为了避免临界区的竞态条件发生,有多种手段可以达到目的。

  • 阻塞式的解决方案:synchronized,Lock
  • 非阻塞式的解决方案:原子变量

synchronized,即俗称的【对象锁】,它采用互斥的方式让同一时刻至多只有一个线程能持有【对象锁】,其它线程再想获取这个【对象锁】时就会阻塞住。这样就能保证拥有锁的线程可以安全的执行临界区内的代码,不用担心线程上下文切换。

synchronized的三个作用

  1. 原子性:确保线程互斥的访问同步代码
  2. 可见性:保证共享变量的修改能够及时可见
  3. 有序性:有效解决重排序问题

2、synchronized的语法


class Test1{
    public synchronized void test() {
    }
}
//等价于
class Test1{
    public void test() {
        //锁的是当前对象
        synchronized(this) {
        }
    }
}

class Test2{
    public synchronized static void test() {
    }
}
//等价于
class Test2{
    public static void test() {
        //锁的是类对象,类对象只有一个
        synchronized(Test2.class) {
        }
    }
}

3、Monitor原理

Monitor 被翻译为监视器或管程

每个 Java 对象都可以关联一个 Monitor 对象,如果使用 synchronized 给对象上锁(重量级)之后,该对象头的 Mark Word 中就被设置指向 Monitor 对象的指针

Monitor 结构如下

  • 刚开始 Monitor 中 Owner 为 null
  • 当 Thread-2 执行 synchronized(obj) 就会将 Monitor 的所有者 Owner 置为 Thread-2,Monitor中只能有一个 Owner
  • 在 Thread-2 上锁的过程中,如果 Thread-3,Thread-4,Thread-5 也来执行 synchronized(obj),就会进入EntryList BLOCKED
  • Thread-2 执行完同步代码块的内容,然后唤醒 EntryList 中等待的线程来竞争锁,竞争的时是非公平的
  • 图中 WaitSet 中的 Thread-0,Thread-1 是之前获得过锁,但条件不满足进入 WAITING 状态的线程

注意:不加 synchronized 的对象不会关联监视器

4、synchronized的原理

通过对Java代码进行反编译可知,Synchronized的语义底层是通过一个monitor的对象来完成,
其实wait/notify等方法也依赖于monitor对象,这就是为什么只有在同步的块或者方法中才能调用wait/notify等方法,否则会抛出java.lang.IllegalMonitorStateException的异常的原因。

jdk5引入了现代操作系统新增加的CAS原子操作( JDK5中并没有对synchronized关键字做优化,而是体现在J.U.C中,所以在该版本concurrent包有更好的性能 ),从JDK6开始,就对synchronized的实现机制进行了较大调整,包括使用JDK5引进的CAS自旋之外,还增加了自适应的CAS自旋、锁消除、锁粗化、偏向锁、轻量级锁这些优化策略。由于此关键字的优化使得性能极大提高.

锁主要存在四种状态,依次是:无锁状态、偏向锁状态、轻量级锁状态、重量级锁状态,锁可以从偏向锁升级到轻量级锁,再升级的重量级锁。但是锁的升级是单向的,也就是说只能从低到高升级,不会出现锁的降级。

在 JDK 1.6 中默认是开启偏向锁和轻量级锁的,可以通过-XX:-UseBiasedLocking来禁用偏向锁。

4.1偏向锁

Java 6 中引入了偏向锁来做进一步优化:只有第一次使用 CAS 将线程 ID 设置到对象的 Mark Word 头,之后发现 这个线程 ID 是自己的就表示没有竞争,不用重新 CAS。以后只要不发生竞争,这个对象就归该线程所有。

 

调用了对象的 hashCode,但偏向锁的对象 MarkWord 中存储的是线程 id,如果调用 hashCode 会导致偏向锁被撤销

  • 轻量级锁会在锁记录中记录 hashCode
  • 重量级锁会在 Monitor 中记录 hashCode

4.2轻量级锁

轻量级锁的使用场景:如果一个对象虽然有多线程要加锁,但加锁的时间是错开的(也就是没有竞争),那么可以使用轻量级锁来优化。
轻量级锁对使用者是透明的,即语法仍然是 synchronized。

引入轻量级锁的主要目的是 在没有多线程竞争的前提下,减少传统的重量级锁使用操作系统互斥量产生的性能消耗。当关闭偏向锁功能或者多个线程竞争偏向锁导致偏向锁升级为轻量级锁,则会尝试获取轻量级锁。

4.3锁膨胀

如果在尝试加轻量级锁的过程中,CAS 操作无法成功,这时一种情况就是有其它线程为此对象加上了轻量级锁(有 竞争),这时需要进行锁膨胀,将轻量级锁变为重量级锁。

4.4重量级锁

Synchronized是通过对象内部的一个叫做 监视器锁(Monitor)来实现的。但是监视器锁本质又是依赖于底层的操作系统的Mutex Lock来实现的。而操作系统实现线程之间的切换这就需要从用户态转换到核心态,这个成本非常高,状态之间的转换需要相对比较长的时间,这就是为什么Synchronized效率低的原因。因此,这种依赖于操作系统Mutex Lock所实现的锁我们称之为 “重量级锁”。

4.5自旋锁

线程的阻塞和唤醒需要CPU从用户态转为核心态,频繁的阻塞和唤醒对CPU来说是一件负担很重的工作,势必会给系统的并发性能带来很大的压力。同时我们发现在许多应用上面,对象锁的锁状态只会持续很短一段时间,为了这一段很短的时间频繁地阻塞和唤醒线程是非常不值得的。

所以引入自旋锁,何谓自旋锁?

所谓自旋锁,就是指当一个线程尝试获取某个锁时,如果该锁已被其他线程占用,就一直循环检测锁是否被释放,而不是进入线程挂起或睡眠状态。

4.6锁消除

消除锁是虚拟机另外一种锁的优化,这种优化更彻底,Java虚拟机在JIT编译时(可以简单理解为当某段代码即将第一次被执行时进行编译,又称即时编译),通过对运行上下文的扫描,去除不可能存在共享资源竞争的锁,通过这种方式消除没有必要的锁,可以节省毫无意义的请求锁时间,如下StringBuffer的append是一个同步方法,但我们将StringBuffer作为一个局部变量使用,并且不会被其他线程所使用,因此StringBuffer不可能存在共享资源竞争的情景,JVM会自动将其锁消除。

4.7锁粗化

在使用同步锁的时候,需要让同步块的作用范围尽可能小—仅在共享数据的实际作用域中才进行同步,这样做的目的是 为了使需要同步的操作数量尽可能缩小,如果存在锁竞争,那么等待锁的线程也能尽快拿到锁。

在大多数的情况下,上述观点是正确的。但是如果一系列的连续加锁解锁操作,可能会导致不必要的性能损耗,所以引入锁粗话的概念。

锁粗话概念比较好理解,就是将多个连续的加锁、解锁操作连接在一起,扩展成一个范围更大的锁

5、锁升级过程

各种锁并不是相互代替的,而是在不同场景下的不同选择,绝对不是说重量级锁就是不合适的。每种锁是只能升级,不能降级,即由偏向锁->轻量级锁->重量级锁,而这个过程就是开销逐渐加大的过程。

如果是单线程使用,那偏向锁毫无疑问代价最小,并且它就能解决问题,连CAS都不用做,仅仅在内存中比较下对象头就可以了;

如果出现了其他线程竞争,则偏向锁就会升级为轻量级锁;

如果其他线程通过一定次数的CAS尝试没有成功,则进入重量级锁;

总结

本篇文章就到这里了,希望能给你带来帮助,也希望您能够多多关注编程网的更多内容!

--结束END--

本文标题: JAVAsynchronized原理详解

本文链接: https://lsjlt.com/news/133090.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • JAVAsynchronized原理详解
    目录1、synchronized的作用2、synchronized的语法3、Monitor原理4、synchronized的原理4.1偏向锁4.2轻量级锁4.3锁膨胀4.4重量级锁4...
    99+
    2024-04-02
  • Javasynchronized偏向锁的核心原理详解
    目录1. 偏向锁的核心原理2. 偏向锁的撤销3. 偏向锁的膨胀4. 偏向锁的好处总结1. 偏向锁的核心原理 轻量级锁在没有竞争时(就自己这个线程),每次重入仍然需要执行 CAS 操作...
    99+
    2024-04-02
  • Javasynchronized轻量级锁的核心原理详解
    目录1. 轻量级锁的原理2. 轻量级锁的分类1、普通自旋锁2、自适应自旋锁3. 轻量级锁的膨胀总结问题: 什么是自旋锁? 说一下 synchronized 底层实现原理? 多线程中 ...
    99+
    2024-04-02
  • Javasynchronized底层的实现原理
    目录监视器底层实现执行流程总结前言: 想了解 synchronized 是如何运行的?就要先搞清楚 synchronized 是如何实现? synchronized 同步锁是通过 J...
    99+
    2024-04-02
  • Javasynchronized同步方法详解
    目录1. synchronized 同步方法2. synchronized 方法将对象作为锁3. 多个锁对象4. 如果同步方法内的线程抛出异常会发生什么?5. 静态的同步方法总结面试...
    99+
    2024-04-02
  • Javasynchronized与CAS使用方式详解
    目录引言synchronizedsynchronized的三种使用方式synchronized的底层原理JDK1.6对synchronized的优化synchronized的等待唤醒...
    99+
    2023-01-16
    Java CAS Java synchronized
  • JavaSynchronized的偏向锁详细分析
    目录理论知识源码论证总结上篇文章已经对Synchronized关键字做了初步的介绍,从字节码层面介绍了Synchronized关键字,最终字节码层面就是monitorenter和mo...
    99+
    2023-05-15
    Java synchronized偏向锁 Java synchronized Java偏向锁
  • EventBus详解 (详解 + 原理)
    一、EventBus的使用介绍 EventBus简介 EventBus是一个开源库,由GreenRobot开发而来,是用于Android开发的 “事件发布—订阅总线”, 用来进行模块间通信、解藕。它可以使用很少的代码,来实现多组件之间...
    99+
    2023-08-31
    android
  • React 原理详解
    目录1.setState() 说明1.1 更新数据1.2 推荐语法1.3 第二个参数2.JSX 语法的转化过程3.组件更新机制4.组件性能优化4.1 减轻 state4.2 避免不必...
    99+
    2024-04-02
  • Nacos 原理详解
    一. 背景 现如今市面上注册中心的轮子很多,我实际使用过的就有三款:Eureka、Nacos,Zookeeper、Consul 由于当前参与Nacos 集群的维护和开发工作,期间也参与了 Nacos ...
    99+
    2023-09-03
    服务发现 java 微服务 nacos nacos源码
  • Java ShutdownHook原理详解
    目录ShutdownHook介绍ShutdownHook原理ShutdownHook的数据结构与执行顺序ShutdownHook触发点Shutdown.exitShutdown.sh...
    99+
    2024-04-02
  • mysql mvcc 原理详解
    前言 很多人在谈起mysql事务的时候都能很快的答出mysql的几种事务隔离级别,以及在各自隔离级别下产生的问题,但是一旦谈到为什么会产生这样的结果时会觉得难以回答,说到底,还是对底层的原理未做深入的探究,本篇将从较为底层的原理层面来聊聊...
    99+
    2023-09-17
    mvcc mysql mvcc原理 mvcc 原理详解 mysql mvcc说明 mysql mvcc详解
  • SELINUX工作原理详解
    1. 简介 SElinux带给Linux的主要价值是:提供了一个灵活的,可配置的MAC机制。     Security-Enhanced Linux (SELinux)由以下两部分组成: ...
    99+
    2022-06-04
    SELINUX 工作原理
  • MySQL索引原理详解
    目录索引是什么索引数据结构树形索引树的动画为什么不是简单的二叉树?为什么不是红黑树?为什么最终选择B+树 而不是B树水平方向可以存放更多的索引key数据量估算叶子节点包含所有的索引字段叶子节点直接包含双向指针,范围查找效...
    99+
    2022-08-19
    MySQL索引原理 MySQL索引
  • monogdb复制原理详解
    一、复制介绍复制是在多台服务器之间同步数据的过程。 复制在为数据提供了冗余同时,也提高了数据的可用性。由于在不同的数据库服务器上拥有多个数据镜像,复制可以有效的防止由于单台服务器故障而导致的数据丢...
    99+
    2024-04-02
  • Flashback Data Archive原理详解
    Flashback Data Archive  11g版本的Oracle database 中提供的flashback data  archive 能够查看过去任何时间表的状态...
    99+
    2024-04-02
  • 详解Redis复制原理
    目录前言一.配置与实践配置实践只读二.工作原理三.数据同步全量复制部分复制前言 本文主要介绍Redis复制机制 一.配置与实践 配置 Redis实例分为主节点(master)和从节...
    99+
    2024-04-02
  • Spring Cloud Feign原理详解
    目录Feign的大体机制@EnableFeignClients 和 @FeignClient 注解registerDefaultConfiguration方法registerFeig...
    99+
    2024-04-02
  • js Proxy的原理详解
    目录什么是代理模式 引入一个现实生活中的案例结合案例理解代理模式的定义什么是Proxyget(target, propKey, receiver) set(target, propK...
    99+
    2024-04-02
  • 详解MyBatis工作原理
    目录一、Mybatis工作原理二、Mybatis运行原理总结一、Mybatis工作原理 Mybatis分层框架图 Mybatis工作原理图 源码分析:一般都是从helloworl...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作