synchronized底层实现

synchronized底层实现

synchronized时Java的内建锁,可以保证在多线程的情况下,每次有且仅有一个线程访问共享资源
同步的原理:monitor机制
同步代码块

class TestMonitor implements Runnable{
    @Override
    public void run() {
        synchronized (this){
            System.out.println("hello Java");
        }
    }
}
public class MonitorDemo {
    public static void main(String[] args) {
        TestMonitor testMonitor = new TestMonitor();
        Thread thread = new Thread(testMonitor);
        thread.start();
    }
}

通过javap命令查看响应字节码文件
在这里插入图片描述
执行同步代码块后首先要执行monitorenter指令,退出时执行monitorexit指令。
使用内建锁(synchronized)进行同步,关键在于要获取指定锁对象,当线程获取monitor后才能继续向下执行,否则就只能等待。这个过程是互斥的,即同一时刻只有一个线程能够获取到对象monitor。
为什么会有两个monitorexit?
通常一个monitorenter指令会包含若干个monitorexit指令。原因在于jvm需要确保在正常执行路径以及异常执行路径上都要能够正确的解锁。(正确与否都要确保正确解锁)
同步方法:


在这里插入图片描述
可以看到字节码中包含ACC_SYNCHRONIZED这样的标志位,这个标记表示,在进入该方法时,JVM需要进行monitorenter操作。在退出该方法时,无论是正常还是异常,都要进行monitorexit操作

  • 当执行monitorenter时,如果目标锁对象的monitor计数器为0,表示此对象没有被任何其他对象所持有。此时jvm会将该锁对象的持有线程设置为当前线程,并且将计数器加1
  • 如果目标锁对象的monitor计数器不为0,判断锁对象的持有线程是否是当前线程,如果是再将计数器加1(锁的可重入性)
  • 如果锁对象的持有线程不是当前线程,当前线程需要等待,直至持有线程释放锁
  • 当执行monitirexit时,jvm会将锁对象的计数器-1.当计数器值减为0时,代表该锁对象已经被释放。

锁的可重入性:

class MyEnter implements Runnable{

    @Override
    public void run() {
        test1();
    }

    public synchronized void test1(){
        System.out.println(Thread.currentThread().getName()+" test1");
        System.out.println("test over,test2 bagin");
        test2();
    }
    public void test2(){
        System.out.println(Thread.currentThread().getName()+" test2");
    }
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值