Java并发编程的艺术-第二章之并发机制的底层实现原理

Java中的并发机制依赖于JVM的实现和CPU指令,接下来我们深入底层探索Java并发机制的实现原理。

1、volatile

      Java中允许线程访问共享变量,为了保证共享变量能够一致的被更新,线程应该确保通过排他锁单独的获取这个变量。Java中就提供了volatile,如果一个字段被声明成volatile,在java线程内存模型确保所有的线程看到的这个变量的值都是一致的。

volatile是一种轻量级synchronized,而且执行的成本比较低,没有上下文切换的消耗。volatile修饰的共享变量在进行写操作的时候,在多处理器下会引起两件事:

(1)、将当前处理器缓存行的数据写会到系统内存

(2)、这个回写操作会使得CPU中其他的处理器缓存了该地址的数据无效。

对于高速缓存行是64个字节宽的处理器,如果队列的头节点和尾节点都不足64字节的话,处理器会将他们读到同一个高速缓存行,修改头节点时,会将整个缓存行锁定,导致其它的处理器不能读到自己的高速缓存区的尾节点。影响出队列和入队列操作的效率。追加64字节能够对volatile的性能进行优化,避免头节点和尾节点同时加载到同一个高速缓存行中,避免互相锁定。


2、synchronized

上面的追加字节的方式可能在Java 7 中生效,它会淘汰或重排序无用的字段,除了volatile,Java中用的较多的的synchronized,下面看一下:

synchronized是一种重量级锁,Java中每个对象多可以作为锁,具体是下面3种形式:
(1)、普通同步方法,锁是当前实例对象

(2)、静态同步方法,琐是当前类的Class对象

(3)、同步方法块,锁是synchronized 括号里配置的对象

synchronized用的锁是存在Java对象头的,对象头中有字段标示当前是哪种锁,锁一共4种状态、级别由低到高:无锁状态、偏向锁状态、轻量级锁、重量级锁


三种锁的对比
优点缺点适用场景
  偏向锁加锁和解锁不需要额外的消耗,                           如果线程间存在锁的竞争,会带来额外的锁撤销的消耗     适用于只有一个线程访问同步块的场景
   轻量级锁         竞争的线程不会阻塞,提高了线程的响应时间如果始终得不到锁竞争的线程,会自旋消耗CPU追求响应时间,同步块执行非常快 
   重量级锁线程竞争不会使用自旋,不会消耗CPU,线程阻塞,响应时间缓慢 追求吞吐量,同步块执行速度较慢


3、原子操作

原子操作是指不可中断的一个或一系列的操作,一般的处理器是利用总线加锁或者缓存加锁的方式实现多处理器之间的原子操作。

总线锁定:处理器提供一个LOCK # 信号,刚一个处理器在总线上输出一个信号时,其它的处理器请求就会被阻塞住,那么该处理器就可以独占共享内存了。

缓存锁定:内存区域如果被缓存在处理器的缓存行中,在Lock操作期间被锁定,在执行锁操作回写到内存时,处理器不在总线上声言LOCK #信号,而是修改内存地址,缓存的一致性机制会阻止同时修改由2个以上处理器缓存的内存区数据,其他的处理器成功回写被锁定的缓存行数据时,会使缓存行无效,其它的处理器就不能在使用这个缓存行了。

Java中是通过使用锁个CAS(atomic包)的方式来实现原子操作。





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值