java锁、同步锁与死锁

乐观锁

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

悲观锁

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

自旋锁

自旋锁原理非常简单,如果持有的锁的线程能在很短时间内释放资源,那么那些等待竞争锁的线程就不需要做内核态和用户态之间的切换进入阻塞挂起状态,他们只需要等一等(自旋),等持有的锁的线程释放锁后即可立即获得锁,这样就避免用户线程和内核的切换的消耗
线程自旋是要消耗cpu的,说白了就是让cpu在做无用功,如果一直获取不到锁,这时争用线程会停止自旋进入阻塞状态。

自旋锁的优缺点

自旋锁尽可能的减少线程的阻塞,这对于锁的竞争不激烈,且占用锁时间非常短的代码块来说性能能大幅度的提升,因为自旋的消耗会小于线程阻塞挂起再唤醒的操作的消耗,这些操作会导致线程发生两次上下文切换!
但是如果锁的竞争激烈,或者持有锁的线程需要长时间占用锁执行同步块,这时候就不适合使用自旋锁了,因为自旋锁在获取锁前一直在做无用功,同时有大量的线程在竞争一个锁,会导致获取锁的时间很长,线程自旋的消耗大于线程阻塞挂起操作的消耗,其他需要cou的线程又不能获取到cpu,造成cpu的浪费,所以这种情况我们要关闭自旋锁

自旋锁时间阀值

自旋锁的目的是为了占着spu的资源不释放,等到获取锁立即进行处理。但是如何去选择自旋的执行时间呢?如果自旋执行时间太长,会导致大量的线程处于自旋状态占用cpu资源,进而会影响整体系统的性能。因此自旋的周期选的额外重要!

jvm会对自旋的周期的选择,jdk15这个限度是一定写死的,在1.6引入了适应性自旋锁,适用性自旋锁意味着自旋的时间不是固定的了,而是由上一次在同一个锁上的自旋时间以及锁的拥有者的状态来决定的,基本认为一个线程上下文切换的时间是最佳的一个时间,同时jvm还会对当前负荷的情况做了较多的优化,如果平均负载小于CPUs则一直自旋,如果有超过CPUs/2个线程正在自旋,则后来线程直接阻塞,如果正在自旋的线程发现Owner发生了变化则延迟自旋时间(自旋技术)或进入阻塞,如果cpu处于节电模式则停止自旋,自旋时间的最坏情况就是cpu的存储延迟(CPU A 存储了一个数据,到CPU B得知这个数据的直接的时间差),自旋时会适当放弃线程优先级之间的差异

自旋锁的开启

JDK1.6中-XX:+UserSpinning开启
-XX:PreBlockSpin=10 为自选次数
JDK1.7后,去掉此参数,由jvm控制;

Synchronized

synchronize 可以把任意一个非null的对象当做锁。他属于独占式的悲观锁,同时属于可重入锁

synchronize作用范围

  1. .作用于方法时,锁住的是对象的实例;
  2. 当作用于静态方法时,锁住的是对象的Class实例,又因为Class的相关数据存储在永久带PermGen(jdk1.8 则是metaspace),永久带是全局共享的,因此静态方法相当于类的一个全局锁,会锁所有调用该线程的方法
  3. synchronized作用于一个对象实例时,锁住的是所有以该对象为锁的代码块。他有多个队列,当多个线程一起访问某个对象监视器的时候,对象监视器会将这些线程存储在不同的容器中

synchronize 核心组件

  • Wait Set :哪些调用wait方法被阻塞的线程被放置在这里
  • Contention List :竞争队列,所有请求锁的线程首先被放在这个竞争队列中;
  • Entry List :collection List中哪些有资格成为候选资源的线程被移到Entry List中
  • OnDeck:任意时刻,最多只有一个线程在竞争锁资源,该线程被称为OnDeck
  • Owner:当前已经获取到所资源的线程被称为Owner
  • !Owner:当前释放锁的线程

Synchronized实现

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值