当前位置: 首页 > news >正文

复习之 java 锁

裁员在家,没有面试机会,整理整理面试知识点吧!

不得不知道的java 锁

Java 中,提供了两种方式来实现同步互斥访问(也就是锁):synchronized 和 Lock

多线程编程中,有可能会出现多个线程同时访问同一个共享、可变资源的情况,这个资源我们称之其为临界资源;

这种资源可能是: 对象、变量、文件等。
共享:资源可以由多个线程同时访问
可变:资源可以在其生命周期内被修改
当多个线程执行一个方法时,该方法内部的局部变量并不是临界资源,因为这些局部变量是在每个线程的 ,私有栈中,因此不具有共享性,不会导致线程安全问题。
synchronized
jvm 内置的锁,可以对临界资源同步访问,是可重入的。
实例方法加锁:锁的是当前对象。同一个线程

静态方法加锁:锁的是当前类对象

静态代码块:锁的是代码块里的对象

synchronized底层原理
synchronized 是基于JVM 的内置锁,底层通过通过内部Monitor(监视器锁)实现,监视器锁的实现依赖底层操作系统的Mutex lock(互斥锁)实现,它是一个重量级锁性能较低。jdk1.5 以后哦哦进行了优化。偏向锁,轻量级锁(自适应自旋锁),重量级锁。使得synchronized 性能跟Lock 差不多。 
synchronized关键字被编译成字节码后会被翻译成 monitorenter monitorexit 两条指令分别在同步块逻辑代码的起始位置
与结束位置。
对象结构
一个对象包括:对象头,对象数据,对其填充
对象头包括:
      markworld :用于存储对象自身运行时数据,比如hashcode,GC分代年龄,锁状态标志,线程持有的锁,线程偏向ID,偏向时间戳等,
      klass : 对象指向它的类元数据指针,虚拟机通过这个指针确定这个对象是哪个类的实例
      数组长度(数组才有)
synchronized 锁升级过程
1 首先一个线程t1请求加锁资源,此时对象头里线程偏向id 存储当前线程的线程id,并且锁的状态标志位加锁。现在是一个偏向锁
2 当再有第二个线程t2过来尝试加锁,发现已经被加锁了,检查加锁的是否是自己,不是t2 则尝试修改对象头偏向id 为自己,修改失败,当t1 运行到安全点时,判断是否t1 已经退出代码块,如果是则t1 释放锁,t2 添加偏向锁,如果t1没有执行完,则升级为轻量级锁
3 轻量级锁,t2 会通过CAS 方式自旋尝试加锁,超过多少次没有获取到锁,则升级成重量级锁,因为自旋获取锁,也是比较费CPU 资源的

锁粗话 StringBubber .append 线程安全,多次append 就会进行一个锁 锁粗话

锁清除 synchronized (new object()) ,因为每次都是锁新对象,jvm 认为没有意思 所以不会加锁 

逃逸分析:如果一个对象只有在一个线程栈中用到,没有其他线程用到,这样这个对象就会在一部分会在栈中不放到堆里。

ReentrantLock 时基于AQS 实现的同步手段,跟synchronized 也是一种互斥锁。保证线程安全。但是它又比synchronized 多了很多特性,比如:公平锁,中断锁,锁超时等等。
ReentrantLock 原理
1 通过cas 方式 设置变量,expect–期望值  update–新值,如果期望值跟内存值相等,修改内存值为新的值。当前线程设置独占访问
 unsafe.compareAndSwapInt(this, stateOffset, expect, update);
setExclusiveOwnerThread(Thread.currentThread()); 

2 如果期望值跟内存之不相等,则获取共享变量判断是否等0 如果等于,则说明没有加锁,通过cas 继续加锁,如果不能与获取设置的线程,跟当前线程比对是否相等,如果相等则说明相同线程加锁,可以继续加锁,重入锁。

3 如果既不能加锁,也不是重入锁。则把当前线程放入队列里

核心思想:就是线程请求一个共享资源,如果共享资源空闲,这对共享资源加锁,如果共享资源已经加锁,则进入阻塞状态以及被唤醒时分配机制。通过CLH队列(虚拟双向队列)实现锁的,既获得不到锁的加入到队列中。

用大白话来说,AQS就是基于CLH队列,用volatile修饰共享变量state,线程通过CAS去改变状态符,成功则获取锁成功,失败则进入等待队列,等待被唤醒。

ReentrantLock lock = new ReentrantLock(false);//false为非公平锁
lock.lock();
lock.tryLock(30, TimeUnit.SECONDS);// 30秒没加上锁,自动释放
lock.lockInterruptibly();// 锁中断

 Condition condition = lock.newCondition();  //lock 等待通知
 condition.await();
 condition.signal();

 可以替换 synchronized  wait notify  

 obj.wait(); obj.notify(); 在synchronized 里否则报错

死锁:a线程锁定一个资源,同时想获取b线程的资源,b线程锁定一个资源,同时想获取a线程的资源。

java 死锁必要条件
1 互斥条件:资源不能被共享,只能由一个线程使用(threadLocal)  
2 请求保持条件:一个线程因请求其他资源而阻塞时,对目前拥有的资源保持不放。(一次性请求所有资源)

3 不可抢占条件:进程已获得的资源,在未使用完之前,不能被剥夺( 超时500毫秒 ,自动释放锁)  lock.tryLock(timeout)。
4 相互等待条件:t1 修改下单状态,减库存,  t2减库存,下单  相互持有对方的锁 等待,死锁(逻辑顺序一致) 

只要打破上面任意一个条件,即不会死锁

什么情况下会释放synchronized

执行完成会释放锁

抛异常会释放锁

wait 释放当前锁

return 释放锁

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • CMake详解-捡重要的讲
  • 【漏洞复现】某某康达vpn——list_base_config.php——命令执行
  • Qt Xlsx使用教程、Qt操作Excel、Qt生成Excel图表、跨平台不依赖Office 直接使用源码
  • 优化业务流程的关键:深入探讨BPA流程设计
  • qt-11基本对话框(消息框)
  • 【图形验证和AI智能及CHATGPT对抗影响的是用户体验】
  • 【大模型系列篇】Transformers综述--邱锡鹏
  • react的setState中为什么不能用++?
  • pygame开发课程系列(4): 游戏元素
  • 怎么直接在PDF上修改内容?随心编辑PDF内容
  • 日拱一卒(4)——leetcode学习记录:路径总和
  • python爬虫爬取某图书网页实例
  • Nginx禁用IP和IP段
  • 二叉树的判断
  • 详解 Redis 队列 实现
  • HashMap ConcurrentHashMap
  • Iterator 和 for...of 循环
  • js如何打印object对象
  • laravel 用artisan创建自己的模板
  • opencv python Meanshift 和 Camshift
  • php中curl和soap方式请求服务超时问题
  • python3 使用 asyncio 代替线程
  • Swoft 源码剖析 - 代码自动更新机制
  • 阿里中间件开源组件:Sentinel 0.2.0正式发布
  • 服务器从安装到部署全过程(二)
  • 深入体验bash on windows,在windows上搭建原生的linux开发环境,酷!
  • 一份游戏开发学习路线
  • 应用生命周期终极 DevOps 工具包
  • 职业生涯 一个六年开发经验的女程序员的心声。
  • 《码出高效》学习笔记与书中错误记录
  • 阿里云IoT边缘计算助力企业零改造实现远程运维 ...
  • 测评:对于写作的人来说,Markdown是你最好的朋友 ...
  • # C++之functional库用法整理
  • # Spring Cloud Alibaba Nacos_配置中心与服务发现(四)
  • ## 1.3.Git命令
  • #、%和$符号在OGNL表达式中经常出现
  • (07)Hive——窗口函数详解
  • (Git) gitignore基础使用
  • (Matalb分类预测)GA-BP遗传算法优化BP神经网络的多维分类预测
  • (Windows环境)FFMPEG编译,包含编译x264以及x265
  • (附源码)ssm高校运动会管理系统 毕业设计 020419
  • (附源码)ssm旅游企业财务管理系统 毕业设计 102100
  • (力扣题库)跳跃游戏II(c++)
  • (免费领源码)Java#Springboot#mysql农产品销售管理系统47627-计算机毕业设计项目选题推荐
  • (七)Activiti-modeler中文支持
  • (学习日记)2024.03.25:UCOSIII第二十二节:系统启动流程详解
  • (循环依赖问题)学习spring的第九天
  • (一)Linux+Windows下安装ffmpeg
  • (一)pytest自动化测试框架之生成测试报告(mac系统)
  • (一)硬件制作--从零开始自制linux掌上电脑(F1C200S) <嵌入式项目>
  • (原創) 如何安裝Linux版本的Quartus II? (SOC) (Quartus II) (Linux) (RedHat) (VirtualBox)
  • (原創) 如何解决make kernel时『clock skew detected』的warning? (OS) (Linux)
  • (原創) 是否该学PetShop将Model和BLL分开? (.NET) (N-Tier) (PetShop) (OO)
  • (转) Android中ViewStub组件使用
  • (转)一些感悟