Java并发编程: Synchronized--值得学习

目录及前言

synchronized 是我们Java程序员在日常开发中常用的同步工具,但是很多人却对它的用法和实现原理一知半解。

  • 怎么合理的运用synchronized ?
  • 什么场景运用 synchronized ?
  • synchronized怎么用?

一. synchronized 的原理

同样 synchronized 保证了  【原子性、有序性、可见性】

1.1 对象的构成

要想了解 synchronized 的原理,首先我们要了解下,对象的构成,因为 synchronized 作用的目标就是在对象上。

Java对象在JVM内存中由三块区域组成:对象头、实例数据和对齐填充。

对象头又包含:Mark Word(标记字段)、Class Pointer(类型指针)数组长度【如果是数组】

  • 实例数据:是对象真正存储的有效信息,也既是我们在程序代码里面所定义的各种类型的字段内容,无论是从父类继承下来的,还是在子类中定义的都需要记录下来。 这部分的存储顺序会受到虚拟机分配策略参数FieldsAllocationStyle和字段在Java源码中定义顺序的影响。HotSpot虚拟机 默认的分配策略为longs/doubles、ints、shorts/chars、bytes/booleans、oops(Ordinary Object Pointers),从分配策略中可以看出,相同宽度的字段总是被分配到一起。在满足这个前提条件的情况下,在父类中定义的变量会出现在子类之前。如果 CompactFields参数值为true(默认为true),那子类之中较窄的变量也可能会插入到父类变量的空隙之中。

  • 对齐填充没有特殊含义,由于虚拟机要求 对象起始地址必须是8字节的整数倍,作用仅是字节对齐。

  • Class Pointer是对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。

1.1 对象监视器

JVM 是通过进入、退出 对象监视器(Monitor) 来实现对方法、同步块的同步的,而对象监视器的本质依赖于底层操作系统的 互斥锁(Mutex Lock) 实现。 具体实现是在编译之后在同步方法调用前加入一个monitor.enter指令,在退出方法和异常处插入monitor.exit的指令。 对于没有获取到锁的线程将会阻塞到方法入口处,直到获取锁的线程monitor.exit之后才能尝试继续获取锁。

可以看到在同步块的入口和出口分别有monitorenter和monitorexit指令。当执行monitorenter指令时,线程试图获取锁也就是获取monitor(monitor对象存在于每个Java对象的对象头中,synchronized锁便是通过这种方式获取锁的,也是为什么Java中任意对象可以作为锁的原因)的持有权。当计数器为0则可以成功获取,获取后将锁计数器设为1也就是加1。相应的在执行monitorexit指令后,将锁计数器设为0,表明锁被释放。如果获取对象锁失败,那当前线程就要阻塞等待,直到锁被另外一个线程释放为止。 在synchronized修饰方法时是添加ACC_SYNCHRONIZED标识,该标识指明了该方法是一个同步方法,JVM通过该ACC_SYNCHRONIZED访问标志来辨别一个方法是否声明为同步方法,从而执行相应的同步调用。

1.3 特点:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值