1.volatile的应用
1.1 volatile的定义及实现原理
定义:Java编程语言允许线程访问共享变量,为了确保共享变量的准确性好一致性,需要通过排它锁获取这个变量。
volatile实现原则:
(1)处理器缓存写到内存:锁总线;锁缓存
(2)一个处理器的缓存回写到内存会造成其他处理器的缓存无效
volatile使用优化:
由于很多主流处理器的高速缓存行是64字节的字节宽,若队列的头结点和尾节点都不足64字节,处理器会将他们读到同一个缓存行,在多个处理器下每个处理器都会缓存同样的头、尾节点,当一个处理器试图修改头节点,会将整个缓存行锁定,那么在缓存一致性机制的作用下,会导致其他的处理不能访问自己高速缓存中的尾节点,而队列的入列和出列操作需要不停的修改头尾节点,造成性能影响。因此在缓存行是64位字节宽的处理器,共享变量会频繁的读写的情况下,可以使用追加64字节提高编程的效率。
2.synchronized
可以利用synchronized可以锁定每个对象,具体一下3种:
(1)锁定普通同步方法,锁的是当前实例;
(2)锁定静态同步方法,或类,锁定的是当前类的Class对象;
(3)同步方法:锁定的是synchronized挂号中配置的对象。
2.1 Java对象头
synchronized用的锁是存在Java对象头里,普通对象用2个字宽,数组用3个字宽。以下以32位为例:
Mark Word默认保存对象的HashCode,分代年龄和锁标记。
2.2 锁的定义和对比
偏向锁:
在对象头和栈帧中的锁记录存储锁偏向线程的ID,以后该线程在进入和退出同步块时不需要进行CAS加锁和解锁,只需要测试对象头中的Mark World里是否存储当前线程的偏向锁。
轻量级锁:
线程执行同步块之前,在当前线程的栈帧中创建用于存储锁记录的空间,并将对象头中的Mark Word复制到锁记录中,然后线程尝试使用CAS将对象头的Mark Word替换为指向锁记录的指针。