多线程安全——synchronized原理

本文详细探讨了Java中的synchronized关键字,包括其作用范围、代码块和方法的底层实现原理,以及Monitor(管程)的概念。synchronized通过Mark Word和Monitor实现线程安全,涉及无锁、偏向锁、轻量级锁和重量级锁的状态转换。文章还介绍了Mesa模型,并解释了为何每个对象可以作为锁的原因以及wait和notify的机制。
摘要由CSDN通过智能技术生成

synchronized 它可以把任意一个非 NULL 的对象当作锁。他属于独占式的悲观锁,同时属于可重 入锁

作用范围

1. 作用于方法时,锁住的是对象的实例(this);

2. 当作用于静态方法时,锁住的是Class实例,又因为Class的相关数据存储在永久带PermGen (jdk1.8 则是 metaspace),永久带是全局共享的,因此静态方法锁相当于类的一个全局锁, 会锁所有调用该方法的线程;

3. synchronized 作用于一个对象实例时,锁住的是所有以该对象为锁的代码块。它有多个队列, 当多个线程一起访问某个对象监视器的时候,对象监视器会将这些线程存储在不同的容器中。

synchronized有三种方式来加锁,分别是:方法锁对象锁synchronized(this)类锁synchronized(Demo.Class)

synchronized代码块底层原理

public class SynchronizedTest1 {

    private static int count = 0;

    public static void test(){
        synchronized (SynchronizedTest1.class) {
            count++;
        }
    }
}

通过javap -v 来查看对应代码的字节码指令:

对于同步块的实现使用了monitorenter和monitorexit指令:他们隐式的执行了Lock和UnLock操作,用于提供原子性保证。monitorenter指令插入到同步代码块开始的位置、monitorexit指令插入到同步代码块结束位置,jvm需要保证每个monitorenter都有一个monitorexit对应。这两个指令,本质上都是对一个对象的监视器(monitor)进行获取,这个过程是排他的,也就是说同一时刻只能有一个线程获取到由synchronized所保护对象的监视器。线程执行到monitorenter指令时,会尝试获取对象所对应的monitor所有权,也就是尝试获取对象的锁;而执行monitorexit,就是释放monitor的所有权。

synchronized方法底层原理

public class SynchronizedTest2 {

    private static int count = 0;

    public synchronized static void test() {
        count++;
    }
}

方法级的同步是隐式,即无需通过字节码指令来控制的,它实现在方法调用和返回操作之中。

JVM通过该ACC_SYNCHRONIZED 访问标志区分一个方法是否同步方法。当方法调用时,调用指令将会检查方法的 ACC_SYNCHRONIZED 访问标志是否被设置,如果设置了,执行线程将先持有monitor, 然后再执行方法,最后再方法完成(无论是正常完成还是非正常完成)时释放monitor。在方法执行期间,执行线程持有了mo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值