synchronized关键字的底层原理

基本使用

如下抢票的代码,如果不加锁,就会出现超卖或者一张票卖给多个人
Synchronized 【对象锁】采用互斥的方式让同一时刻至多只有一个线程能持有
【对象锁】,其它线程再想获取这个【对象锁】时就会阻塞住
public class TicketDemo {
static Object lock = new Object();
int ticketNum = 10;
public synchronized void getTicket() {
synchronized (this) {
if (ticketNum <= 0) {
return;
}
System.out.println(Thread.currentThread().getName() +
"抢到一张票,剩余:" + ticketNum);
// 非原子性操作
ticketNum--;
}
}
public static void main(String[] args) {
TicketDemo ticketDemo = new TicketDemo();
for (int i = 0; i < 20; i++) {
new Thread(() -> {
ticketDemo.getTicket();
}).start();
}
}
}

Monitor

Monitor 被翻译为监视器,是由 jvm 提供, c++ 语言实现
在代码中想要体现 monitor 需要借助 javap 命令查看 clsss 的字节码,比如以下代
public class SyncTest {
static final Object lock = new Object();
static int counter = 0;
public static void main(String[] args) {
synchronized (lock) {
counter++;
}
}
}
找到这个类的 class 文件,在 class 文件目录下执行 javap - v SyncTest.class ,反
编译效果如下
monitorenter 上锁开始的地方
monitorexit 解锁的地方
其中被 monitorenter monitorexit 包围住的指令就是上锁的代码
有两个 monitorexit 的原因,第二个 monitorexit 是为了防止锁住的代码抛异常后不
能及时释放锁
在使用了 synchornized 代码块时需要指定一个对象,所以 synchornized 也被称为
对象锁
monitor 主要就是跟这个对象产生关联,如下图
Monitor 内部具体的存储结构:
Owner :存储当前获取锁的线程的,只能有一个线程可以获取
EntryList :关联没有抢到锁的线程,处于 Blocked 状态的线程
WaitSet :关联调用了 wait 方法的线程,处于 Waiting 状态的线程
具体的流程:
代码进入 synchorized 代码块,先让 lock (对象锁)关联的 monitor ,然后判断
Owner 是否有线程持有
如果没有线程持有,则让当前线程持有,表示该线程获取锁成功
如果有线程持有,则让当前线程进入 entryList 进行阻塞,如果 Owner 持有的线
程已经释放了锁,在 EntryList 中的线程去竞争锁的持有权(非公平)
如果代码块中调用了 wait() 方法,则会进去 WaitSet 中进行等待

总结

synchronized底层使用的JVM级别中的Monitor来决定当前线程是否获取了锁,如果某一个线程获取到锁,在没有释放锁之前,其他线程是不能或得到锁的。synchronized属于悲观锁。

synchronized因为需要依赖于JVM级别的Monitor,相对性能也会比较低。

关于Monitor,Monitor对象存在于每个java对象头中,synchronized锁便是通过这种方式获取锁的,这也是为什么java中任意对象都可以作为锁的原因。

Monitor内部中维护了三个变量

WaitSet :保存处于 Waiting 状态的线程
EntryList :保存处于 Blocked 状态的线程
Owner :持有锁的线程
只有一个线程获取到的标志就是在 monitor 中设置成功了 Owner ,一个
monitor 中只能有一个 Owner
在上锁的过程中,如果有其他线程也来抢锁,则进入 EntryList 进行阻塞,当
获得锁的线程执行完了,释放了锁,就会唤醒 EntryList 中等待的线程竞争
锁,竞争的时候是非公平的。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值