深入理解与应用多线程技术( 二 )


 
作用:

  • 可见性: 当一个线程修改了一个被 volatile 修饰的变量的值,其他线程能够立即看到这个修改,即保证了变量的可见性 。
  • 禁止指令重排序: volatile 修饰的变量的读写操作会禁止指令重排序,确保变量的写操作不会被重排序到其它操作之前 。
原理:
volatile 的实现原理涉及到 CPU 的缓存一致性和内存屏障(Memory Barrier)的概念 。
  • 内存可见性: 当一个线程写入一个 volatile 变量时,会强制将该线程对应的本地内存中的值刷新到主内存中,从而保证了其他线程能够看到最新的值 。同样,当一个线程读取一个 volatile 变量时,会强制从主内存中读取最新的值到本地内存中 。
  • 禁止指令重排序: volatile 修饰的变量的读写操作会在其前后插入内存屏障,防止在其前后的指令被重排序 。
synchronized 的实现原理以及锁优化如果synchronized作用于代码块,反编译可以看到两个指令:monitorenter、monitorexit,JVM使用monitorenter和monitorexit两个指令实现同步;如果作用synchronized作用于方法,反编译可以看到ACCSYNCHRONIZED标记,JVM通过在方法访问标识符(flags)中加入ACCSYNCHRONIZED来实现同步功能 。
  • 同步代码块,当线程执行到monitorenter的时候要先获得monitor锁,才能执行后面的方法 。当线程执行到monitorexit的时候则要释放锁 。
  • 同步方法,当线程执行有ACCSYNCHRONI标志的方法,需要获得monitor锁 。每个对象都与一个monitor相关联,线程可以占有或者释放monitor 。
monitor监视器操作系统的管程(monitors)是概念原理,ObjectMonitor是它的原理实现 。
深入理解与应用多线程技术

文章插图
图片
在JAVA虚拟机(HotSpot)中,Monitor(管程)是由ObjectMonitor实现的,其主要数据结构如下:
ObjectMonitor() {_header= NULL;_count= 0; // 记录个数_waiters= 0,_recursions= 0;_object= NULL;_owner= NULL;_WaitSet= NULL;// 处于wait状态的线程,会被加入到_WaitSet_WaitSetLock= 0 ;_Responsible= NULL ;_succ= NULL ;_cxq= NULL ;FreeNext= NULL ;_EntryList= NULL ;// 处于等待锁block状态的线程,会被加入到该列表_SpinFreq= 0 ;_SpinClock= 0 ;OwnerIsThread = 0 ;}Java Monitor 的工作机理
深入理解与应用多线程技术

文章插图
图片
  • 要获取monitor的线程,首先会进入EntryList队列 。
  • 当某个线程获取到对象的monitor后,进入Owner区域,设置为当前线程,同时计数器count加1 。
  • 如果线程调用了wait()方法,则会进入WaitSet队列阻塞等待 。它会释放monitor锁,即将owner赋值为null,count自减1 。
  • 如果其他线程调用 notify()/notifyAll() ,会唤醒WaitSet中的某个或全部线程,该线程再次尝试获取monitor锁,成功即进入Owner区域 。
  • 同步方法执行完毕了,线程退出临界区,会将monitor的owner设为null,并释放监视锁
对象与monitor关联
深入理解与应用多线程技术

文章插图
图片
  • 在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header),实例数据(Instance Data)和对象填充(Padding) 。
  • 对象头主要包括两部分数据:Mark word(标记字段)、Class Pointer(类型指针) 。
Mark Word 是用于存储对象自身的运行时数据,如哈希码(HashCode)、GC分代年龄、锁状态标志、线程持有的锁、偏向线程 ID、偏向时间戳等 。
深入理解与应用多线程技术

文章插图
图片
重量级锁,指向互斥量的指针 。其实synchronized是重量级锁,也就是说Synchronized的对象锁,Mark Word锁标识位为10 , 其中指针指向的是Monitor对象的起始地址 。
 
在JDK1.6之前,synchronized的实现直接调用ObjectMonitor的enter和exit , 这种锁被称之为重量级锁 。从JDK6开始 , HotSpot虚拟机开发团队对Java中的锁进行优化 , 如增加了适应性自旋、锁消除、锁粗化、轻量级锁和偏向锁等优化策略,提升了synchronized的性能 。


推荐阅读