首页 > 编程语言 >JAVA基础:lock锁底层机制

JAVA基础:lock锁底层机制

时间:2024-09-25 20:22:17浏览次数:9  
标签:count 状态 JAVA lock 线程 赋值 底层

目录

lock锁底层机制

乐观锁


lock锁底层机制

lock锁底层使用的是CAS + AQS,在lock底层有一个计数器,记录锁被获取的状态,起初为0 , 当被抢占的时候变为1

当我们调用lock.lock()方法,就是将状态从0改为1的过程。当我们调用lock,unlock()方法时,就是将状态从1改为0的过程

当我们调用lock.lock方法时,如果发现状态是1,表示锁被占用,当前线程进入等待状态

当多个线程同时访问lock.lock()方法时,每个线程都尝试着将状态从0改为1. 假设a线程最先完成状态改变,a线程获得了锁。此时b线程也尝试将0改为1,先获得原始值0,将0改为1,再将改好的1替换原始值0(赋值)

在替换前,会拿着之前的原始值与现在变量里的值进行比较,看看是否发生了变化

如果没有变化,说明这个过程中没有其他线程访问资源,将其改为1获得锁。

如结发生了变化,说明这个过程中被其他线程捷足先登了,其他的线程获得锁,当前线程等待

我们称这个过程为 CAS (compare and set)

当一个线程获得锁时,发现锁已经被占用了,当前这个线程就会处于等待状态

实际上,并不是线程对象有一个状态码,改为等待状态的值。

而是将需要等待的线程,存入了一个集合,并使其进入最终等待状态(jvm级别的等待状态)

当最开始线程执行完毕释放锁后,就会从这个集合中取出最开始的那个线程继续执行

这个集合我们就称为 AQS (抽象的)队列同步器

乐观锁

乐观锁不是一种真正存在的锁,一种机制

底层使用的是 CAS + 自旋 应用组合
假设线程1获得count值为0并记录为原始值
接着会对0实现++操作,变成1
接着会尝试将1赋值回count变量中
然后会根据之前记录的原始值0 与此时count变量中的值比较

 如果相等,说明这个过程中没有其他线程修改count值,表示这段时间当前线程占有这个变量
 完成赋值

  如果不相等。比如count已经=2了,说明这个过程中,有其他线程使用过这个变量
  如果继续赋值,影响了其他线程的操作结果,所以不能赋值,此次操作失败
  重新获取现在的最新的值,记录为原始值2,重复操作 ,直到能够完成赋值位置
  我们称这个重复过程为:自旋

标签:count,状态,JAVA,lock,线程,赋值,底层
From: https://blog.csdn.net/weixin_65346668/article/details/142531179

相关文章

  • java读取寄存器数据
    一:概述在嵌入式系统或硬件编程中,Java通常不是首选语言,因为它运行在虚拟机上,与硬件层面的交互不够直接。然而,随着Java技术的发展,以及JNA(JavaNativeAccess)等库的出现,使得Java也能进行一些底层操作,包括读取寄存器数据。本文将探讨几种在Java中读取寄存器数据的方法,并提供实际案例。......
  • Elasticsearch基本概念及底层 【总结】
    随着业务的增长,数据与日俱增,这时为用户带来丰富的、便捷的搜索功能就迫在眉睫了。传统的数据库在处理文本搜索、模糊查询、海量数据统计分析的时候总会力不从心,所以在处理这些复杂的搜索需求时,我们更倾向于使用Elasticsearch搜索引擎。Elasticsearch是一个分布式、RESTf......
  • java读取寄存器数据
    一:概述在嵌入式系统或硬件编程中,Java通常不是首选语言,因为它运行在虚拟机上,与硬件层面的交互不够直接。然而,随着Java技术的发展,以及JNA(JavaNativeAccess)等库的出现,使得Java也能进行一些底层操作,包括读取寄存器数据。本文将探讨几种在Java中读取寄存器数据的方法,并提供实际案例。......
  • 基于Java对数据库的增加和查询操作
     在开始编码前,我们需要先给IDEA配置下面两个jar文件:第一步:我们先进行数据库的连接publicclassDBUtils{/***打开数据库*///优化:让加载器等操作,只做一次publicstaticStringdriver;//驱动地址publicstaticStringurl;//数据库的地......
  • Java中集合泛型的学习
    集合遍历目录集合遍历泛型的基本概念泛型的好处泛型的使用1.泛型类2.泛型接口3.泛型方法Java集合框架中的泛型泛型通配符Java集合泛型是JavaSE1.5(Java5)中引入的一个重要特性,它允许在定义类、接口和方法时指定一个或多个类型参数。这些类型参数在实例化或调用时会被具体的......
  • Java毕业设计-基于SSM框架的校园失物招领平台系统项目实战(附源码+论文)
    大家好!我是程序猿老A,感谢您阅读本文,欢迎一键三连哦。......
  • Java毕业设计-基于SSM框架的网上奶茶店系统项目实战(附源码+论文)
    大家好!我是程序猿老A,感谢您阅读本文,欢迎一键三连哦。......
  • Java中CountDownLatch和CyclicBarrier的区别与详解
    Java中CountDownLatch和CyclicBarrier的区别与详解一.CountDownLatch和CyclicBarrier的区别CountDownLatch的计数器是大于或等于线程数的,而CyclicBarrier是一定等于线程数CountDownLatch放行由其他线程控制而CyclicBarrier是由本身来控制的二.详解CountDownLatch说明:一......
  • javascript向数组添加元素
    javascript向数组添加元素,比较常用的是两种方法,一种是向数组后面添加元素,一种是在数组前面添加元素。向数组后面添加元素,一般用push语句,它返回的是添加新元素之后的数组长度。push语法格式是数组名.push('要添加的数组元素')比如有一个数组名字叫arr,要向数组后面添加一个'g......
  • 关于 ReentrantLock 中锁 lock() 和解锁 unlock() 的底层原理浅析
    关于ReentrantLock中锁lock()和解锁unlock()的底层原理浅析一、描述如下代码,当我们在使用ReentrantLock进行加锁和解锁时,底层到底是如何帮助我们进行控制的啦?staticLocklock=newReentrantLock();publicstaticvoidmain(String[]args){/......