synchronized原理你知道吗?

1.概念

synchronized 是利用锁的机制来实现同步的,而锁的机制有两种特性:

a.互斥性:即在同一时间只允许一个线程持有某个对象锁,通过这种特性来实现多线程种的协调机制,这样在同一时间内只有一个线程对需同步的代码块进行访问,互斥操作往往也被叫做原子操作,具有原子性.

b.可见性:必须确保在锁被释放之前,对共享变量锁做的修改,对于随后的获得该锁的另一个线程是可见的,可见底层是采用内存屏障去强行刷到主存或者高速缓存中的.

2.synchronized的用法

1.同步方法

Public synchronized void methodName(){

 //业务逻辑

}

2.同步代码块

synchronized(this or object or .class) {}

3.synchronized底层原理实现

在java中,当方法或者类或者代码块使用了sychronized的时候,每个对象都会创建一个monitor对象,这个对象称为"内置锁"或者"对象锁".

在加入synchronized的时候在JVM层面其实是加了Monitorenter指令和Monitorexit指令

在monitorenter指令之后,Load屏障会加一个Acquire屏障,这个屏障可以禁止读操作和写操作之间发生指令重排序,这就可以保证sychronized的有序性,内部可以重排序,但无法和外部指令发生重排序,还会进行一个refresh操作,保证数据的可见性.

在monitorexit指令之后,会有一个store屏障,他会让线程把自己在同步中改变的变量都执行flush操作,把变量刷到高速缓存,或者主内存中去.

两个指令可以使得synchronized拥有可见性和有序性.

对象在堆里面被创建是内存中的布局分为 对象头 ,实例数据和对齐填充.

对象头一般包含两个信息:

1.自身的运行时数据:如 锁的状态,线程持有锁 这部分内容一般叫Mark Word

2.类型指针:JVM通过这个指针来确定对象是哪个类的实例.

 

上图就是一个完整的synchronized原理图

1.对象实例创建的时候会在对象头创建一个markWord区域,里面就包含了ObjectMonitor对象的指针.

2.ObjectMonitor对象包含 count (计数器),owner(属于哪个线程调用),waiset(需要被唤醒的线程集合),waitSetLock(唤醒后进行加锁),entryList(等待加锁的线程集合)

 

调用链路: 当多个线程去调用一个synchronized方法时,首先会保存在entryList中,接下来利用CAS(乐观锁比较替换)对计数器count进行比较看当前数值是否为0 , 如果当前数值为0 则加锁成功,owner就会记录当前线程属于哪个线程调用,如果调用了wait方法则进入waitset线程集合中等待.

并且synchronized是可重入锁,相同的线程可以重复进入 每进入一次计数器+1,出去则-1.

正是这种加锁 释放锁的过程使得ObjectMonitor整个流程是原子性的.要么加锁成功 要么加锁失败.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你今天学习了吗?

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值