栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

JAVA锁

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JAVA锁

乐观锁与悲观锁

乐观锁:

        乐观锁是一种乐观思想,即认为读多写少,遇到并发的可能性低,每次去拿数据的时候都认为别人不会去修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,采取在写时先读出当前版本号,然后加速操作(比较跟上一次的版本号,如果一样则更新),如果失败则要重复读-比较-写的操作

java中乐观锁基本都是通过CAS操作实现的,CAS是一种更新的原子操作,比较当前值跟传入值是否一样,一样则更新,否则失败。

悲观锁:

        悲观锁就是悲观的思想,即认为写多,遇到并发写的可能性高,每次去拿数据的时候都认为别人会修改,所以每次在读写数据的时候都会上锁,这样别想读写这个数据就会block直到拿到锁。java中的悲观锁就是Synchronized,AQS框架下的锁则是先尝试cas乐观锁去获取锁,获取不到才会转换为悲观锁,如RetreenLock。

公平锁与非公平锁

非公平锁:

        JVM按随机、就近原则分配锁的机制称为不公平锁,RetreenLock在构造函数中提供了是否公平锁的初始化方式,默认为非公平锁。非公平锁实际执行的效率要远远超过公平锁,除非程序有特殊需要,否则最常用非公平锁的分配机制。

加锁时不考虑排队等待问题,直接尝试获取锁,获取不到自动到队尾等待

1. 非公平锁性能比公平锁高 5~10 倍,因为公平锁需要在多核的情况下维护一个队列 2. Java 中的 synchronized 是非公平锁,ReentrantLock 默认的 lock()方法采用的是非公平锁。 公平锁:                  公平锁指的是锁的分配机制是公平的,通常先对锁提出获取请求的线程会先被分配到锁, ReentrantLock 在构造函数中提供了是否公平锁的初始化方式来定义公平锁 加锁前检查是否有排队等待的线程,优先排队等待的线程,先来先得 ReadWriteLock 读写锁:                  为了提高性能,Java 提供了读写锁,在读的地方使用读锁,在写的地方使用写锁,灵活控制 ,如果没有写锁的情况下,读是无阻塞的,在一定程度上提高了程序的执行效率。读写锁分为读锁和写锁,多个读锁不互斥,读锁与写锁互斥,这是由 jvm自己控制的,你只要上好相应的锁即可。 读锁: 如果你的代码只读数据,可以很多人同时读,但不能同时写,那就上读锁 写锁: 如果你的代码修改数据,只能有一个人在写,且不能同时读取,那就上写锁。总之,读的时候上 读锁,写的时候上写锁! Java 中读写锁有个接口 java.util.concurrent.locks.ReadWriteLock ,也有具体的实现 ReentrantReadWriteLock。 共享锁和独占锁:

        

独占锁:

        独占锁模式下,每次只能有一个线程能持有锁,ReentrantLock 就是以独占方式实现的互斥锁。 独占锁是一种悲观保守的加锁策略,它避免了读/读冲突,如果某个只读线程获取锁,则其他读线 程都只能等待,这种情况下就限制了不必要的并发性,因为读操作并不会影响数据的一致性。 共享锁:         共享锁则允许多个线程同时获取锁,并发访问 共享资源,如:ReadWriteLock。共享锁则是一种 乐观锁,它放宽了加锁策略,允许多个执行读操作的线程同时访问共享资源。 1. AQS 的内部类 Node 定义了两个常量 SHARED 和 EXCLUSIVE,他们分别标识 AQS 队列中等 待线程的锁获取模式。 2. java 的并发包中提供了 ReadWriteLock,读-写锁。它允许一个资源可以被多个读操作访问, 或者被一个 写操作访问,但两者不能同时进行。          锁的状态总共有四种:无锁状态、偏向锁、轻量级锁和重量级锁 偏向锁:                    Hotspot 的作者经过以往的研究发现大多数情况下锁不仅不存在多线程竞争,而且总是由同一线 程多次获得。 偏向锁的目的是在某个线程获得锁之后,消除这个线程锁重入(CAS)的开销,看起 来让这个线程得到了偏护 。引入偏向锁是为了在无多线程竞争的情况下尽量减少不必要的轻量级 锁执行路径,因为轻量级锁的获取及释放依赖多次 CAS 原子指令, 而偏向锁只需要在置换 ThreadID 的时候依赖一次 CAS 原子指令 (由于一旦出现多线程竞争的情况就必须撤销偏向锁,所 以偏向锁的撤销操作的性能损耗必须小于节省下来的 CAS 原子指令的性能消耗)。上面说过, 轻 量级锁是为了在线程交替执行同步块时提高性能 , 而偏向锁则是在只有一个线程执行同步块时进 一步提高性能 。 轻量级锁:                  轻量级”是相对于使用操作系统互斥量来实现的传统锁而言的。但是,首先需要强调一点的是, 轻量级锁并不是用来代替重量级锁的,它的本意是在没有多线程竞争的前提下,减少传统的重量级锁使用产生的性能消耗。在解释轻量级锁的执行过程之前,先明白一点 ,轻量级锁所适应的场景是线程交替执行同步块的情况,如果存在同一时间访问同一锁的情况,就会导致轻量级锁膨胀为重量级锁。 重量级锁( Mutex Lock )                    Synchronized 是通过对象内部的一个叫做监视器锁(monitor)来实现的。但是监视器锁本质又是依赖于底层的操作系统的 Mutex Lock 来实现的。而操作系统实现线程之间的切换这就需要从用户态转换到核心态,这个成本非常高,状态之间的转换需要相对比较长的时间,这就是为什么 Synchronized 效率低的原因。因此, 这种依赖于操作系统 Mutex Lock 所实现的锁我们称之为 “重量级锁” 。JDK 中对 Synchronized 做的种种优化,其核心都是为了减少这种重量级锁的使用。 JDK1.6 以后,为了减少获得锁和释放锁所带来的性能消耗,提高性能,引入了“轻量级锁”和 “偏向锁”。          同步锁与死锁 同步锁:                  当多个线程同时访问同一个数据时,很容易出现问题。为了避免这种情况出现,我们要保 证线程同步互斥,就是指并发执行的多个线程 ,在同一时间内只允许一个线程访问共享数据。 Java 中可以使用 synchronized 关键字来取得一个对象的同步锁。 死锁:                   何为死锁,就是多个线程同时被阻塞,它们中的一个或者全部都在等待某个资源被释放。                                    

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/778867.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号