Java并发编程(二)-- synchronized

从上一篇讲线程中,我们了解到了线程的各个状态,以及如何状态间的转换。此篇来温习下,线程的阻塞状态与运行态是怎样的转换过程。

synchronized

我们知道,多个线程相互配合的完成某一项工作,必然牵扯到对共享资源的竞争。而synchronized关键字便是有效实现多个线程间同步操作的利器,可以使共享资源在同一时间只能被一个线程享用,从而保证了线程对共享资源的可见性和排他性,实现线程安全。
synchronized,可以修饰方法,使方法成为同步方法,或者修饰代码块,使之成为同步块,二者的作用都是一样。举个简单例子,然后剖析:

public class TestSynchronized {
    public static void main(String[] args) {
        synchronized (TestSynchronized.class){
        }
    }
    public  static synchronized void  a(){

    }
}

执行javap,查看该代码的字节码:
synchronized例子
main方法中的synchronized方法,转换为monitorenter和monitorexit指令。而同步方法中加了ACC_SYNCHRONIZED来标识。
这两种方式的实质都是通过一个对象的监视器(monitor)来进行的,执行方法的线程必须获取到了对象的monitor才能进入synchronized修饰的方法体内,也就是同一时刻只能有一个线程获取到monitor。如果线程未获取到monitor,那么将进入阻塞状态,阻塞在同步块或方法的入口。

线程与monitor

线程与monitor的关系如下:
线程与monitor的关系
任何线程获取synchronized保护的对象资源时,必须先获得对象的监视器。若获取monitor失败,则进入同步队列,线程变为阻塞状态。当获取了对象资源的线程释放了monitor后,会唤醒阻塞在同步队列中等待的线程,让队首的线程重新尝试获取monitor。

当程序线程进入monitorenter指令时,即占用了monitor锁,monitor就处于锁定状态。过程如下:

  1. 如果monitor的进入数为0,则该线程进入monitor,然后将进入数设置为1,该线程即为monitor的所有者。
  2. 如果线程已经占有该monitor,只是重新进入,则进入monitor的进入数加1。
  3. 如果其他线程已经占用了monitor,则该线程进入阻塞状态,直到monitor的进入数为0,再重新尝试获取monitor的所有权。
    当程序执行到monitorexit时,monitor的进入数减1,如果减1后monitor的进入数是0,该线程释放monitor的所有权,其他线程尝试获取monitor所有权。

所以synchronized的特性之一–可重入性,体现在monitor进入数的递增,大于1表示已经重入了多锁。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值