Java并发——Synchronized和Volatile

Java并发同步机制

一、Synchronized

1》实现方式及原理

它的使用方法有以下三种

  • 同步普通方法,锁当前实例对象(对这个类的对象操作需要获取锁)
  • 同步静态方法,锁当前Class对象(这个类new的对象不会加锁,而调用类的静态方法需要获取锁)
  • 同步代码块,锁代码块范围内的对象

一个线程访问一个类的static synchronized方法时,其他线程可以访问该类的非static synchronized的方法。原因是两个线程所获得的锁不同,前者是锁住的是这个类,而后者锁着的是这个实例对象,因此不存在互斥关系。

在JVM层面,synchronized的实现是通过monitor指令实现的

同步代码块:

  • 进入同步范围时,monitorentry指令
  • 退出代码块范围或者异常退出时,monitorexit指令

同步方法:

  • 执行到synchronized修饰的方法时会有ACC_SYNCHRONIZED标志

2》锁升级

jdk1.6对synchronized进行了大量优化 

  1. 偏向锁 
  2. 轻量级锁
  3. 重量级锁

偏向锁:大多数情况下认为线程是不存在竞争的,这样加锁和释放锁无疑是浪费了资源,一个线程访问资源时,如果对象头中存储的线程ID为这个线程的ID时,不需要进行CAS加锁和释放锁。(偏向锁升级成轻量级锁)线程ID不为此线程时,检查对象头中锁标志是否为偏向锁,如果不是,则通过CAS竞争锁,如果是,则通过CAS将对象头的线程ID指向当前线程。此时如果CAS修改对象头的线程ID失败,则证明出现锁的竞争,锁升级成轻量级锁。

轻量级锁:加锁之前,JVM会在当前栈帧中创建存储锁记录的空间,将对象头中的Mark Word 复制到锁记录中,然后线程使用CAS将对象头中的Mark Word的线程ID改成指向当前线程,如果成功,获取锁。(轻量级锁升级成重量级锁)如果CAS失败,则进入自旋状态尝试获取该锁,如果直到自旋结束都没有获取成功,则该轻量级锁膨胀为重量级锁,并且阻塞后面的其他竞争该锁的线程。当获取锁的线程执行完毕,此时释放锁通过CAS将对象头中的信息重新替换回去,如果CAS成功则线程成功释放锁,如果CAS失败则说明存在其他线程竞争此时锁已经膨胀为重量级锁,此时释放锁并且唤醒被阻塞的线程。

重量级锁:多个线程进行竞争锁,只有一个会获取锁,其余进入阻塞队列。其实现的原理都离不开monitor(监视器),monitor包含一下属性,owner:初始为null,线程占有锁时,owner指向该线程,entryset:竞争锁的队列,waitset:当对象调用wait()时,线程进入此队列,当对象调用notify或者notifyall时,重新进入entryset。关系如下图

                                                      

3》锁优化

  1. 自旋锁
  2. 锁粗化
  3. 锁消除

自旋锁就是轻量级锁那样,不进行阻塞,先自旋获取锁。锁粗化是对于同一个对象一系列的加锁,例如循环中使用StringBuffer,每次append都会加锁,jvm调优会执行锁粗化,就会每次让加锁范围到第一个append开始,到第二个append结束,每两次加一个锁,这样无疑提高了效率。锁消除就是对于局部变量(不可能共享的数据)进行加锁,jvm会进行无锁化。

二、volatile

volite关键字有两个特性:可见性和有序性。

可见性需要了解Java内存模型(JMM),这里简单介绍一下,JMM的提出是为了解决不同操作系统的内存读取存放的规则不同而造成的困难,实现内存读写的同一,每个线程有自己的工作内存,也叫做缓存,线程更改数据会先存到缓存中,然后在更新到主内存中,主内存是公共内存,是线程间进行交流的方式。

1》可见性

当被volite关键字修饰的变量值改变了,lock前缀指令会使其直接更新到主内存中,缓存一致性原则会使其他线程的缓存失效,只能从主内存中重新获取。

2》有序性

当执行到volite关键字时,变量会更新到主存,保证可见性,此时,如果其他线程以此变量的参数为启动条件,而volite之后的代码还没执行,volite保证了这种情况不会发生,即禁止指令重排。

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值