手握Synchronized原理搞懂并发编程,阿里面试官:快到碗里来

Synchronized原理

简介

synchronized想必大家都不陌生,用来解决线程安全问题的利器。同时也是Java高级程序员面试比较常见的面试题。下面会带大家彻底了解synchronized的实现。

内容导航

  1. 什么时候需要用Synchronized
  2. synchronized的使用
  3. synchronized的实现原理分析

什么时候需要用Synchronized

想必大家对synchronized都不陌生,主要作用是在多个线程操作共享数据的时候,保证对共享数据访问的线程安全性。

比如在下面这个图片中,两个线程对于i这个共享变量同时做i++递增操作,那么这个时候对于i这个值来说就存在一个不确定性,也就是说理论上i的值应该是2,但是也可能是1。而导致这个问题的原因是线程并行执行i++操作并不是原子的,存在线程安全问题。所以通常来说解决办法是通过加锁来实现线程的串行执行,而synchronized就是java中锁的实现的关键字。

手握Synchronized原理搞懂并发编程,阿里面试官:快到碗里来

 

synchronized在并发编程中是一个非常重要的角色,在JDK1.6之前,它是一个重量级锁的角色,但是在JDK1.6之后对synchronized做了优化,优化以后性能有了较大的提升(这块会在后面做详细的分析)。

先来看一下synchronized的使用

Synchronized的使用

synchronized有三种使用方法,这三种使用方法分别对应三种不同的作用域,代码如下

修饰普通同步方法

将synchronized修饰在普通同步方法,那么该锁的作用域是在当前实例对象范围内,也就是说对于 SyncDemosd=newSyncDemo();这一个实例对象sd来说,多个线程访问access方法会有锁的限制。如果access已经有线程持有了锁,那这个线程会独占锁,直到锁释放完毕之前,其他线程都会被阻塞

public SyncDemo{
 Object lock =new Object();
 //形式1
 public synchronized void access(){
 //
 }
 //形式2,作用域等同于形式1
 public void access1(){
 synchronized(lock){
 //
 }
 }
 //形式3,作用域等同于前面两种
 public void access2(){
 synchronized(this){
 //
 }
 }
}

修饰静态同步方法

修饰静态同步方法或者静态对象、类,那么这个锁的作用范围是类级别。举个简单的例子,

SyncDemo sd=SyncDemo();
SyncDemo sd2=new SyncDemo();} 

两个不同的实例sd和sd2, 如果sd这个实例访问access方法并且成功持有了锁,那么sd2这个对象如果同样来访问access方法,那么它必须要等待sd这个对象的锁释放以后,sd2这个对象的线程才能访问该方法,这就是类锁;也就是说类锁就相当于全局锁的概念,作用范围是类级别。

这里抛一个小问题,大家看看能不能回答,如果不能也没关系,后面会讲解;问题是如果sd先访问access获得了锁,sd2对象的线程再访问access1方法,那么它会被阻塞吗?

public SyncDemo{
 static Object lock=new Object();
 //形式1
 public synchronized static void access(){
 //
 }
 //形式2等同于形式1
 public void access1(){
 synchronized(lock){
 //
 }
 }
 //形式3等同于前面两种
 public void access2(){
 synchronzied(SyncDemo.class){
 //
 }
 }
}

步方法块

public SyncDemo{
 Object lock=new Object();
 public void access(){
 //do something
 synchronized(lock){
 //
 }
 }
}

通过演示3种不同锁的使用,让大家对synchronized有了初步的认识。当一个线程视图访问带有synchronized修饰的同步代码块或者方法时,必须要先获得锁。当方法执行完毕退出以后或者出现异常的情况下会自动释放锁。如果大家认真看了上面的三个案例,那么应该知道锁的范围控制是由对象的作用域决定的。对象的作用域越大,那么锁的范围也就越大,因此我们可以得出一个初步的猜想,synchronized和对象有非常大的关系。那么,接下来就去剖析一下锁的原理

Synchronized的实现原理分析

当一个线程尝试访问synchronized修饰的代码块时,它首先要获得锁,那么这个锁到底存在哪里呢?

对象在内存中的布局

synchronized实现的锁是存储在Java对象头里,什么是对象头呢?在Hotspot虚拟机中,对象在内存中的存储布局,可以分为三个区域:对象头(Header)、实例数据(Instance Data)、对齐填充(Padding)

手握Synchronized原理搞懂并发编程,阿里面试官:快到碗里来

 

当我们在Java代码中,使用new创建一个对象实例的时候,(hotspot虚拟机ÿ

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值