Synchroniezd、volatile与lock区别
一、Synchroniezd
jvm中对象放在堆内存中的,对象大致可以分为三个部分,分别是对象头,实例变量和填充字节
对象头,主要包括两部分1. Mark Word (标记字段),2.Klass Pointer(类型指针)。Klass Point 是对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例(即指向方法区类的模版信息)。Mark Word用于存储对象自身的运行时数据
实例变量,存放类的属性数据信息,包括父类的属性信息,这部分内存按4字节对齐
1.使用场景
1.修饰实例方法
2.修饰静态方法
3.修饰代码块
2.锁升级
在java1.6之后Synchroniezd引入猎人偏向锁和轻量级锁
升级过程 无锁→偏向锁→轻量级锁→重量级锁
过程:
偏向锁升级:
当线程1访问加锁代码块时,偏向锁进行记录threadID。当线程2进入时判断是否为线程1,
若为线程1则无需进入轻量级锁,若不为线程1则判断1是否存活若线程1不存活则对锁进行释放,进入无锁状态,将线程2设为偏向锁。
若线程1存活则释放线程1,则暂停线程2,将线程1升级为轻量级锁。
轻量级锁升级:
线程1获取轻量级锁时,若线程2也进行获取,此时线程2发现对象头已被线程1更改,cas失败。
线程2进行自旋等待线程1的释放,此时若线程2的自旋次数达到最大,线程1未被释放或正在执行,线程3此时进入轻量级锁。线程2进行膨胀变为重量级锁。
*锁的升级是不可降行为
2.特性
1.有序性
2.可见性:内存强制刷新
3.原子性:单一线程持有
4.可重入性
5.不可中断性
二、Volatile
1.使用场景
某个属性被多个线程共享,其中有一个线程修改了此属性,其他线程可以立即得到修改后的值,比如booleanflag;或者作为触发器,实现轻量级同步。
2.如何保证安全性
在单例双重检查中实现可见性和禁止指令重排序
3.与Synchronize的区别
volatile只能修饰实例变量和类变量,而synchronized可以修饰方法,以及代码块。
volatile保证数据的可见性,但是不保证原子性(多线程进行写操作,不保证线程安全);而synchronized是一种排他(互斥)的机制。
volatile用于禁止指令重排序:可以解决单例双重检查对象初始化代码执行乱序问题。
volatile可以看做是轻量版的synchronized,volatile不保证原子性,但是如果是对一个共享变量进行多个线程的赋值,而没有其他的操作,
那么就可以用volatile来代替synchronized,因为赋值本身是有原子性的,而volatile又保证了可见性,所以就可以保证线程安全了。
三、与Lock区别
1.synchronize是有jvm提供,lock由jdk提供具有丰富的api
2.synchronize为自动释放锁,lock为手动释放锁
3.synchronize为不可中断,lock可中断也可不中断
4.lock可知道线程是否有锁,synchronize不能
5.synchronize可锁代码块和方法,lock不能
6.lock可使用读锁提高多线程效率
7.synchronize非公平锁,lock可为公平锁也可不为公平锁