并发编程--线程同步之 synchronized关键字(一)

线程同步主要就是两种实现:

  • ReentrantLock 显示锁
  • Synchronized 隐式锁

一、对synchronized的一个整体认知

1、JDK1.6之前

整体了解那肯定就得从synchronized升级前后开始了解,正所谓士别三日当刮目相待,JDK1.6之前,synchronized确实很笨重,因为他是强依赖于操作系统的,不管你多少个线程,他都默认你竞争激烈,直接上重头戏,哈哈。

2、JDK1.6后,包含1.6

但是JDK1.6则对synchronized做了重大优化,引入了锁粗化,锁消除,偏向锁,轻量级锁,自旋锁等技术来减小锁操作的开销。
就比如当有一个线程时,就是偏向锁。
当两三个线程,但是由于执行速度快,所以竞争不激烈的情况,则是轻量级锁,就比如有线程A,B,C,A拿到线程,B,C两个线程并非严格等待阻塞着,而是循环请求,等待A释放,就是因为本身的竞争不激烈,这也就是所谓的自旋锁。
假如循环了100次还未拿到锁,这种就有可能升级成重量级锁去竞争。
在这里插入图片描述

二、锁的膨胀升级过程:

锁的状态总共有四种,无锁状态、偏向锁、轻量级锁和重量级锁。随着锁的竞争,锁可以从偏向锁升级到轻量级锁,再升级的重量级锁,但是锁的升级是单向的,也就是说只能从低到高升级,不会出现锁的降级。从JDK 1.6 中默认是开启偏向锁和轻量级锁的,可以通过-XX:-UseBiasedLocking来禁用偏向锁。

1、偏向锁

偏向锁是Java 6之后加入的新锁,它是一种针对加锁操作的优化手段。
经过研究发现,在大多数情况下,锁不仅不存在多线程竞争,而且总是由同一线程多次获得,因此为了减少同一线程获取锁(会涉及到一些CAS操作,耗时)的代价而引入偏向锁。
比如线程A有可能多次获得锁,当线程A获取了锁,那么引入偏向锁的概念之后,当再次请求锁时,无需再做任何同步操作,即获取锁的过程,这样就省去了大量有关锁申请的操作,从而也就提供程序的性能

默认开启偏向锁
开启偏向锁:-XX:+UseBiasedLocking -XX:BiasedLockingStartupDelay=0
关闭偏向锁:-XX:-UseBiasedLocking

2、轻量级锁

倘若偏向锁失败,虚拟机并不会立即升级为重量级锁,它还会尝试使用一种称为轻量级锁的优化手段(1.6之后加入的),此时Mark Word 的结构也变为轻量级锁的结构。
轻量级锁能够提升程序性能的依据是“对绝大部分的锁,在整个同步周期内都不存在竞争”。
适应场景:
轻量级锁所适应的场景是线程交替执行同步块的场合,如果存在同一时间访问同一锁的场合,就会导致轻量级锁膨胀为重量级锁。

3、自旋锁

轻量级锁失败后,虚拟机为了避免线程真实地在操作系统层面挂起,还会进行一项称为自旋锁的优化手段。这是基于在大多数情况下,线程持有锁的时间都不会太长,如果直接挂起操作系统层面的线程可能会得不偿失,毕竟操作系统实现线程之间的切换时需要从用户态转换到核心态,这个状态之间的转换需要相对比较长的时间,时间成本相对较高,因此自旋锁会假设在不久将来,当前的线程可以获得锁,因此虚拟机会让当前想要获取锁的线程做几个空循环(这也是称为自旋的原因),一般不会太久,可能是50个循环或100循环,在经过若干次循环后,如果得到锁,就顺利进入临界区。如果还不能获得锁,那就会将线程在操作系统层面挂起,这就是自旋锁的优化方式,这种方式确实也是可以提升效率的。最后没办法也就只能升级为重量级锁了。

三、可修饰的对象

synchronized内置锁是一种对象锁(锁的是对象而非引用),作用粒度是对象,可以用来实现对临界资源的同步互斥访问,是可重入的。

  1. 修饰一个代码块,
    被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象
  2. 修饰一个方法
    被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象
  3. 修改一个静态的方法
    其作用的范围是整个静态方法,作用的对象是这个类的所有对象
  4. 修改一个类
    其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象

其实理解也就两类,一种是this,取的锁是对象(代码块,非静态方法);一种是class,取的锁是类(静态方法,类)。
下篇则针对原理,实践理解。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值