Synchronized底层实现,及1.6之后的优化,并与Volatile的对比

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhangjingao/article/details/84201431

Synchronized底层实现,及1.6之后的优化,并与Volatile的对比

synchronized这个关键字在面试中经常用到,我这里之前学过一些,在此抛砖引玉,大家有什么其他见解尽可提出。

本文不准备介绍synchronized的具体使用方法,主要探讨底层实现原理

底层实现

  其实可以想一下,这么一个关键字是怎么锁住程序的呢??它有很多种用法,锁对象,锁类对象。总之就是锁对象.
  那么好了,大家应该知道,既然是锁,只有在多线程下才有意义,所以一定有一个共享变量用来记录是不是被锁住了,并且还要保证这个变量能够被所有线程访问。
   了解过计算机操作系统的应该知道,信号量机制,互斥信号量机制一说,那么此时这个共享变量就可以说是一个信号量,并且是互斥信号量。
  那么它存在于哪呢,它存在于每个java的对象头中,叫做monitor(监视器锁)
   大家可以写一段java代码,其中用上synchronized关键字,然后编译一下,使用javap -c Test这个命令来查看Test.java编译后的字节码文件,
   你会发现在使用synchronized使用的程序前后多了两段代码,一个monitorenter,一个monitorexit,顾名思义,就是监视器进入和退出的地方,初始值为0,获取锁后+1,只有当monitor为0时,才能获取成功,否则获取失败,该线程就会进入阻塞状态,直到获得锁的线程释放锁,而它能获得锁。

注意:锁方法时不一样啊,锁方法使用的不是monitor这个家伙了,使用的是ACC_SYNCHRONIZED标识,使用了这个后标明这是一个同步方法,原理和锁对象一致。

jdk1.6之后的优化操作

   在jdk1.6之前,synchronized属于重量级锁,monitor(监视器锁)依赖于底层操作系统的Lock实现,java的线程是映射到操作系统的原生线程上,切换成本较高(从用户态-内核态),每一个切换线程,锁线程都要使用操作系统的方式,这个太麻烦,太笨重了。
   在1.6之后引进了自旋锁,适应性自旋锁,锁粗化,轻量级锁等技术。
   锁有四种状态:无锁状态,偏向锁状态,轻量级锁状态,重量级锁状态,锁的竞争会随着状态的升级而变得激烈,锁只能升级,不能降级,获得锁和释放锁的效率会随着锁的升级而提高。

Volatile的对比

作用:

  1. 保证变量的可见性。
  2. 防止指令重排。

  自jdk1.2之后,java的内存模型做了改变,为了提高运行速度和性能,线程对于变量的操作不是直接读主存,在寄存器中保存时会去读取寄存器中变量的值,那这样之后就有了一个问题。
   在多线程情况下,就可能造成一个线程修改了主存中变量的值,而其他线程还在使用寄存器中变量的值,这就破坏了数据的一致性,使用volatile关键字,是告诉JVM,这个变量是不稳定的,随时可能改变,所以每次使用都要从主存中读取,不能从寄存器中读取。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值