多线程:synchronized关键字解析

原理

synchronized是JVM层面的锁,是一种重量级的锁。synchronized可以同步方法和代码块。

public class Synchronized {
    public static void main(String[] args) {
    // 对Synchronized Class对象进行加锁
        synchronized (Synchronized.class) {
        }
    // 静态同步方法,对Synchronized Class对象进行加锁
        m();
    }
    public static synchronized void m() {
    }
}

执行javap - v Synchronized

public static void main(java.lang.String[]);
// 方法修饰符,表示:public staticflags: ACC_PUBLIC, ACC_STATIC
    Code:
        stack=2, locals=1, args_size=1
        0: ldc #1  // class com/murdock/books/multithread/book/Synchronized
        2: dup
        3: monitorenter  // monitorenter:监视器进入,获取锁
        4: monitorexit   // monitorexit:监视器退出,释放锁
        5: invokestatic  #16 // Method m:()V
        8: return

    public static synchronized void m();
    // 方法修饰符,表示: public static synchronized
    flags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZED
        Code:
            stack=0, locals=0, args_size=0
            0: return

方法级别的同步是隐式的,无需通过字节码指令来控制,它依靠的是方法表里的ACC_SYNCHRONIZED标志(什么是方法表和标志?),当方法调用时,调用指令会检查方法的ACC_SYNCHRONIZED是否被设置了,如果被设置了执行线程首先需要持有管程才能执行方法,执行后或异常时释放管程。

而代码块级别的同步依靠的是monitorenter和monitorexit指令,这两个指令总是成对执行的,在程序异常时编译器会生成一个异常处理器来执行monitorexit指令。

无论采用哪种方式,都是对一个对象的监视器或叫做管程(Monitor)进行获取,这个过程是排他的,也就是同一时刻只可以有一个线程获取到有synchronized保护对象的监视器。获取不到的线程会阻塞在同步方法或同步块的入口处,进入BLOCKED阻塞状态。这里要区别一下阻塞状态和等待状态,使用Object的wait方法后会进入等待队列,notify后唤醒线程从等待队列移入到阻塞(同步)队列。线程正常结束或者异常释放monitor。

以下是对象,对象的监视器,同步队列以及执行线程的关系

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值