您好!欢迎来到爱源码

爱源码

热门搜索: 抖音快手短视频下载   

5000字| 24张图带你穿越Java中的21种锁。 <源码分享>

  • 时间:2022-09-07 01:44 编辑: 来源: 阅读:304
  • 扫一扫,手机访问
摘要:5000字| 24张图带你穿越Java中的21种锁。 <源码分享>
本文已收录在我的Java在线文档和Github对我的SpringCloud实战项目的持续升级中,帮你总结好锁:1。乐观锁定乐观锁定是一种乐观的思想,假设当前环境是多读少写,遇到并发写的概率比较低。读取数据时,认为其他线程不会进行修改(因此它是解锁的)。 写数据时,判断当前值是否与期望值相同,如果相同,则升级(升级时锁定,保证原子性)。 Java中的乐观锁:CAS,比较替换,比较当前值(主存中的值),如果与期望值(当前线程中的值,主存中的值的副本)相同则升级,否则继续CAS操作。 如上图所示,可以同时读,其他线程不能写。 2.悲观锁定悲观锁定是一种悲观思想,即多写少读,并发写的可能性高。每次去取数据的时候都以为剩下的线程会被修改,所以每次读写数据的时候都会被锁死。 当其他线程想要读写这些数据时,它会被这个线程阻塞,直到这个线程释放锁,然后其他线程获得锁。 Java中的悲观锁:同步修饰方法和方法块,ReentrantLock 如上图所示,只有一个线程可以读写,其他线程都不能读写。 3.自旋锁自旋锁是一种技术:为了让线程等待,我们只需要让线程执行一个忙循环(Spin)。 目前,大多数个人计算机和服务器都是多通道(核心)解析器系统。如果一台物理机有多个解析器或解析器核,并且可以同时并行执行两个或两个以上的线程,那么可以在不放弃解析器执行时间的情况下,让后面请求锁的线程“等一会儿”,看看持有锁的线程能否很快释放锁。 自旋锁的优点:避免了线程切换的开销。 挂起和恢复线程的操作需要在内核状态下完成,这给Java虚拟机的并发性能带来了很大的压力。 自旋锁的缺点:如果用的时间长,会白白消耗解析器的资源,不会做任何有价值的工作,带来性能的浪费。 因此,自旋的等待时间必须有一个确定的界限。如果自旋超过了限定的次数,而锁仍然没有被成功获取,那么线程应该以传统的方式被挂起。 默认旋转次数:10次,可以使用参数-xx: preblockpin进行更改。 自适应自旋:自适应意味着自旋时间不再是固定的,而是由前一个锁的自旋时间和锁所有者的状态决定的。 有了自适应自旋,随着程序运行时间的增加和性能监控信息的完善,虚拟机对程序锁状态的预测会越来越准确。 Java中的自旋锁:CAS操作中比较操作失败后的自旋等待 4.重入锁(递归锁)重入锁(recursive lock)是一种技术:任何线程在获得锁之后,都可以再次获得锁,而不会被锁阻塞。 重入锁原理:结合自己设置的同步器可以获得和释放锁。 再次获取锁:识别获取锁的线程是否可以是当前占用锁的线程,如果可以,再次成功获取。 获取锁后,计数递增,然后释放锁:当锁被释放时,计数递减。 Java中的可重入锁:可重入锁、同步修改的方法或代码段 可重入锁的作用:避免死锁 面试问题1:如果增加了两个再入锁,但只释放了一个,会怎么样?答:程序卡住了,线程出不来了。也就是说,如果我们申请了几个锁,就需要释放几个锁。 面试问题二:如果只加一个锁,放两次会怎么样?答:会报错Java . lang . illegalmonitorstateexception。 5.读写锁读写锁是一种技术:它是由ReentrantReadWriteLock类实现的。 为了提高性能,Java提供了读写锁,在读的地方使用读锁,在写的地方使用写锁。可以灵活控制。如果没有写锁,读是畅通的,肯定提高了程序的执行效率。 读写锁分为读锁和写锁,多个读锁不互斥,读锁和写锁互斥,这是jvm自己控制的。 读锁:允许多个线程获得读锁,并同时访问同一资源。 写锁:只允许一个线程获取写锁,不允许同时访问同一个资源。 如何使用:获取和释放读锁获取和释放写锁Java中的读写锁:ReentrantReadWriteLock6。公平锁公平锁是一种思想:多个线程按照申请锁的顺序获取锁。 在并发环境中,每个线程将首先检查由这个锁维护的等待队列。如果当前等待队列为空,它将占用锁。如果等待队列不为空,它将加入等待队列的末尾,根据FIFO规则从队列中获取线程,然后占用锁。 7.不公平锁不公平锁是一种思想:线程试图获取锁,如果不能,就采用公平锁。 多个线程获取锁的顺序不是先来先服务的顺序,有可能后申请锁的线程比先申请锁的线程有优先权。 优点:不公平锁的性能高于公平锁。 缺点:可能会造成线程饥饿(一个线程长时间得不到锁)。Java中的不公平锁:synchronized unfair lock,ReentrantLock通过构造函数指定锁是公平还是不公平,默认为不公平。 8.共享锁共享锁是一个想法:多个线程可以获取读锁,并以共享的方式持有它们。 与乐观锁和读写锁同义。 Java中使用的共享锁:ReentrantReadWriteLock 9.独占锁独占锁是一种思想:只有一个线程可以获得锁并独占它。 它是悲观锁和互斥锁的同义词。 Java中使用的独占锁:synchronized、ReentrantLock10、重量级锁。重量级锁是一个标题:synchronized是通过对象内部的一个监控锁实现的,监控锁本身依赖于底层操作系统的互斥锁。 操作系统需要将线程从客户端状态切换到核心状态,成本非常高。 这种依赖于操作系统互斥锁的锁被称为重量级锁。 为了优化synchonized,引入了轻量级锁,偏向于锁。 Java中的重量级锁:synchronized11、轻量级锁轻量级锁是JDK6中增加的一种锁优化机制:轻量级锁使用CAS操作来消除同步使用的互斥量,而不会产生竞争。 轻量级是相对于使用操作系统互斥锁实现的重量级锁而言的。 轻量级锁可以在没有多线程竞争的情况下,减少传统重量级锁使用操作系统互斥体带来的性能消耗。 如果两个以上的线程竞争同一个锁,那么轻量级锁将无效,必须扩展为重量级锁。 优点:如果没有竞争,通过CAS操作成功避免了使用互斥体的开销。 缺点:如果有竞争,除了互斥本身的开销,还会有CAS操作的额外开销。所以在竞争的情况下,轻量级锁比传统的重量级锁慢。 12.偏向锁偏向锁是JDK6中加入的锁优化机制:全同步无竞争淘汰,连CAS操作都不做。 Bias指的是偏心,也就是说这个锁会偏向第一个获取它的线程。如果在接下来的执行过程中,其他线程没有获得该锁,持有该偏置锁的线程将不再需要同步。 每次有锁偏置的线程进入锁相关的同步块,虚拟机都可以停止任何同步操作(如锁、解锁、升级标志字等。). 优点:它消除了整个同步,甚至CAS操作,优于轻量级锁。 缺点:如果程序中的大部分锁总是被多个不同的线程访问,那么偏向锁是多余的。 13.分段锁分段锁是一种机制:最好的例子说明分段锁是ConcurrentHashMap。 ConcurrentHashMap原理:它在内部细分了几个小HashMap,称为Segment。 默认情况下,ConcurrentHashMap进一步细分为16个段,即锁的并发性。 如果您需要向ConcurrentHashMap添加一个键值,而不是锁定整个HashMap,那么您应该首先获得根据hashcode存储键值的段,然后锁定该段并完成put操作。 在多线程环境中,如果同时放置多个线程,只有添加的键值不存储在同一个段中,那么线程可以真正并行。 线程安全:ConcurrentHashMap是一个段数组,通过继承ReentrantLock来锁定段,所以每个需要锁定的操作都锁定一个段,这样只保证每个段都是线程安全的,从而实现了全局线程安全。14.互斥锁是悲观锁和排他锁的同义词,意味着一个资源只能被一个线程访问,而其余的线程不能。 读-读互斥体读-写互斥体写-读互斥体Java中的同步锁:synchronized15、同步锁同步锁与互斥体同义,是指多个线程并发执行,同一时间只允许一个线程访问共享数据。 Java中的同步锁:synchronized16、死锁死锁是一种现象:如果线程A持有资源X,线程B持有资源Y,线程A等待线程B释放资源Y,线程B等待线程A释放资源X,两个线程都没有释放自己的资源,那么两个线程都无法获得对方的资源,就会导致死锁。 Java中的死锁是无法自行打破的,所以线程死锁后线程无法响应。 所以一定要注意程序的并发场景,避免死锁。 17.锁粗化锁粗化是一种优化技术:如果一系列连续的操作重复锁定和解锁同一个对象,甚至锁定操作发生在循环中,即使真的没有线程竞争,频繁的互斥同步操作也会导致不必要的性能损失,所以采用一种方案:将锁定范围扩展(粗化)到整个操作序列之外,这样锁定和解锁的频率就会大大降低,从而减少。 18.锁消除锁消除是一种优化技术:它是杀死锁。 Java虚拟机运行时,发现有些共享数据不会被线程争用,于是可以消除锁。 如何判断共享数据不会被线程争用?使用逃逸分析技术:分析对象的范围。如果对象在方法A中定义,并作为参数传递给方法B,则称为方法escape如果被其他线程访问,则称为线程转义。 堆上的一些数据不会转义,不会被其他线程访问,也就是说,它可以被当作堆栈上的数据,被认为是线程私有的,所以同步锁是不必要的。 19.synchronizedsynchronized是Java中的关键字:用于修改方法和对象实例。 它属于排他锁、悲观锁、重入锁和不公平锁。 1.作用于实例方法时,它锁定对象的实例(this);2.当用作静态方法时,类被锁定,相当于类的一个全局锁,会锁定所有调用该方法的线程;3.当3.synchronized作用于非null对象实例时,NULL对象作为锁的代码块被锁定。 它有多个队列。当多个线程一起访问一个对象监视器时,对象监视器会将这些线程存储在不同的容器中。 每个对象都有一个监视对象,锁定就是对监视对象的竞争。代码块的锁定是通过在代码块前后添加monitorenter和monitorexit指令来实现的,方法锁定是通过标志位来判断的。 20.锁和同步锁的区别:是Java里的一个接口,可以重锁,悲观,互斥,互斥,同步。 1.锁需要手动获取和释放锁。 就像自动挡和手动挡的区别一样。2.Lock是接口,synchronized是Java里的关键词。synchronized是一种内置的语言实现。 3.3.synchronized异常发生时,会自动释放线程占用的锁,所以不会导致死锁;当锁发生异常时,如果不通过unLock()主动释放锁,很可能会造成死锁,所以在使用锁时需要在finally块中释放锁。 4.Lock可以让等待锁的线程响应中断,synchronized则不能。使用synchronized时,等待线程会一直等待,无法响应中断。 5.通过锁可以知道自己是否成功获取了锁,而synchronized则不能。 6.Lock通过实现读写锁,可以提高多线程读取的效率。 同步的优点:足够清晰和简单。如果您想要基本的同步功能,请使用synchronized。 Lock应该确保锁在finally块中被释放。 如果使用synchronized,JVM确保即使发生异常也能自动释放锁。 使用Lock时,Java虚拟机很难知道具体的线程锁持有哪些锁对象。 21.ReentrantLock和synchronized ReentrantLock的区别是Java中的一个类:它继承了Lock类,可以重锁、悲观、排他、互斥和同步。 重点是一样的:1。它主要处理如何安全访问共享变量的问题;2.都是重入锁,也叫递归锁,同一个线程可以重复获取同一个锁;3.它保证了线程安全性的两个特征:可见性和原子性。 区别:1。Reentrantlock就像手动挡汽车。它需要显示对lock和unlock方法的调用,并获得同步的隐式释放锁。 2.ReentrantLock可以响应中断,但synchronized不能。ReentrantLock提供了更高的灵活性来解决锁不可用的问题。3.ReentrantLock是API级别,synchronized是JVM级别。4.ReentrantLock可以实现公平锁、不公平锁、默认不公平锁、同步不公平锁,不可更改。 5.ReentrantLock可以通过Condition绑定多个条件。


  • 全部评论(0)
资讯详情页最新发布上方横幅
最新发布的资讯信息
【技术支持|常见问题】1556原创ng8文章搜索页面不齐(2024-05-01 14:43)
【技术支持|常见问题】1502企业站群-多域名跳转-多模板切换(2024-04-09 12:19)
【技术支持|常见问题】1126完美滑屏版视频只能显示10个(2024-03-29 13:37)
【技术支持|常见问题】响应式自适应代码(2024-03-24 14:23)
【技术支持|常见问题】1126完美滑屏版百度未授权使用地图api怎么办(2024-03-15 07:21)
【技术支持|常见问题】如何集成阿里通信短信接口(2024-02-19 21:48)
【技术支持|常见问题】算命网微信支付宝产品名称年份在哪修改?风水姻缘合婚配对_公司起名占卜八字算命算财运查吉凶源码(2024-01-07 12:27)
【域名/主机/服务器|】帝国CMS安装(2023-08-20 11:31)
【技术支持|常见问题】通过HTTPs测试Mozilla DNS {免费源码}(2022-11-04 10:37)
【技术支持|常见问题】别告诉我你没看过邰方这两则有思想的创意广告! (2022-11-04 10:37)

联系我们
Q Q:375457086
Q Q:526665408
电话:0755-84666665
微信:15999668636
联系客服
企业客服1 企业客服2 联系客服
86-755-84666665
手机版
手机版
扫一扫进手机版
返回顶部