• java高并发核心要点|系列2|锁的底层实现原理


    上篇文章,我们主要讲了解决多线程之间共享数据的核心问题和解决方案,也讲了锁的简单分类。

    那么,这把锁,我们应该怎么去实现呢?如果你是java语言设计者,你又会怎么去设计这个线程锁呢?

    直觉告诉我们,我们可以设计一个对象或属性,用来代表锁。比如,你把共享数据区当成抽屉,那这个抽屉就可设计出有锁,有钥匙,其实锁和钥匙,就是这个抽屉的必要属性。否则,这个抽屉,也就失去主要用途了。

    是的,java设计者,也是这样的想的。

    在JVM的规范中,有这么一些话:  
      “在JVM中,每个对象和类在逻辑上都是和一个监视器相关联的”  
        “为了实现监视器的排他性监视能力,JVM为每一个对象和类都关联一个锁”  
      “锁住了一个对象,就是获得对象相关联的监视器”

    这三段定义,也许比较模糊又或者比较难懂 。在这里,我们就把监视器,想象成个抽屉就好了,有抽屉就有锁。要访问抽屉,就要拥有这个抽屉的钥匙。

    在java世界中,一般用这几个方法来实现锁与线程同步:synchronized,wait/notify/notifyAll.

    我们知道,synchronized是用来锁定同步代码块或方法或类,那么synchronized,又是如何实现 的呢?

    Synchronized是通过对象内部的一个叫做监视器锁(monitor)来实现的。但是监视器锁本质又是依赖于底层的操作系统的Mutex Lock(互斥锁)来实现的。而操作系统实现线程之间的切换这就需要从用户态转换到核心态,这个成本非常高,状态之间的转换需要相对比较长的时间,这就是为什么Synchronized效率低的原因。因此,这种依赖于操作系统Mutex Lock所实现的锁我们称之为“重量级锁”。JDK中对Synchronized做的种种优化,其核心都是为了减少这种重量级锁的使用。JDK1.6以后,为了减少获得锁和释放锁所带来的性能消耗,提高性能,引入了“轻量级锁”和“偏向锁”。

    那么这个轻量级锁,又是如何实现的呢?

    CAS算法。

    什么是CAS?简单来讲,它就是一条CPU原子指令:Compare and Swap, 翻译成比较并交换。

    CAS有3个操作数,内存值V,旧的预期值A,要修改的新值B。当且仅当预期值A和内存值V相同时,将内存值V修改为B,否则什么都不做。

    简单来说,CPU从指令层级来保证数据的原子性。要么改成最新值,要么什么不做。

    这个就是无锁或轻量级锁的核心知识。


       

    本人精通java高并发,DDD,微服务等技术实践,专注java,rust技术栈。 本人姓名郭莹城,坐标深圳,前IBM架构师、咨询师、敏捷开发技术教练,前IBM区块链研究小组成员、十多年架构设计工作经验,《区块链核心技术与应用》作者之一, 现聚焦于:区块链创投与交易所资源对接和技术咨询。 工作微信&QQ:360369487,区块链创投与交易所资源对接,加我注明:博客园+对接,技术咨询和顾问,加我注明:博客园+顾问。想学习golang和rust的同学,也可以加我微信,备注:博客园+golang或博客园+rust,谢谢!
  • 相关阅读:
    在Windows 10 环境下安装 Hadoop3.1.2
    jQuery选择器分类
    Hibernate 注解的用法以及说明
    EF中Repository模式应用场景
    C# Lambda表达式
    arpd编译错误
    【转】matplotlib画图时的中文设置
    Xt800、DEFY自带号码归属地更新包,更新至2013.4【数据总数278360条】
    80个Python经典资料(教程+源码+工具)汇总
    POJ 1026:Cipher
  • 原文地址:https://www.cnblogs.com/gyc567/p/11015205.html
Copyright © 2020-2023  润新知