juc源码解读六(synchronized)

synchronized在java层面的使用

对于同步方法,jvm采用ACC_SYNCHRONIZED标记符来实现同步;对于同步代码块,jvm采用monitorenter,monitorexit来实现,但都是基于ObjectMonitor实现的;

以类的class对象或类变量为锁

以类class对象为锁有两种写法,如下方式一和方式二,即写在static方法前面,或者synchronized()括号中写xx.class,xx代表某个类;
以类变量为锁有一种写法,即synchronized()括号中写类变量;

方式一

public class A{
public synchronized static void b(…){…}
}
当位于类方法上时,此时是以类class作为锁,此时的作用范围是同一个类的同一个方法,不涉及到实例;

方式二

public class A{
public void b(…){
synchronized(A.class){…}
}
}
因为synchronized(A.class)写在方法中的代码块前面,且入参传入的是A.class所以是以类class作为锁,所以此时的作用范围是同一个类的同一个代码块;
当synchronized的括号中的参数为类变量时,作用范围也是同一个类的同一个代码块;
此时不涉及到实例;
(成员变量和成员方法是范围最大定义,简单而论成员变量包括实例变量和类变量,成员方法包括实例方法和类方法。)

针对以类的class对象或类变量为锁的情况,此时多个线程只要是调用同一个类,就算是不同实例的方法,synchronized也起作用;

以类的实例对象为锁

以类的实例对象为锁有如下两种方式,方式一代表一种写法即写在实例方法名前边,方式二代表另一种写法,即synchronized()括号中可以写this或实例变量;

方式一

public class A{
public synchronized void b(…){…}
}
因为写在实例方法前面,所以是以实例对象为锁,此时的作用范围是同一个实例的同一个方法;

方式二

public class A{
public void b(…){
synchronize(this){…} 以实例对象本身作为锁
}
}
因为synchronize(this)写在方法中的代码块前面,且传入的是this所以是以实例对象为锁,此时的作用范围是同一个实例的同一个代码块;
当传入的是实例变量的时候,此时的作用范围也是同一个实例的同一个代码块;
针对以类的实例变量为锁的情况,此时多个线程只有调用同一个类的同一个实例方法时,synchronized才会起作用;

偏向锁

可通过jvm参数UseBiasedLocking开启或关闭偏向锁,jdk1.6以后默认开启,开启后,程序启动即进入匿名偏向。所以偏向锁流程开始检查是否为匿名偏向,若是匿名偏向则再检查threadId是否为当前线程的id,若不是当前线程的id,则进行cas抢锁,若是当前线程的id则执行同步代码块;若不是匿名偏向,则可能是轻量级锁状态,或者重量级锁状态;
第一步是向当前线程栈内添加一条锁记录,让锁记录中的锁标识指向当前锁对象,这一步无并发,不必用cas;这一步偏向锁,轻量级锁都一致;
第二步是通过cas设置锁对象的markword,存储当前线程的id,这一步需要cas;这一步针对轻量级锁是marword中指向某个

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

orcharddd_real

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值