java synchronized 实现_java中synchronized关键字的实现

本文介绍了Java中同步(synchronized)的实现,包括同步语句块和同步方法。同步语句块通过插入monitorenter和monitorexit指令实现显式同步;同步方法通过ACC_SYNCHRONIZED访问标志实现隐式同步。还阐述了获取和释放锁的内存原语,以及synchronized的可重入性。

说明:

java中的同步(synchronized)是基于进入monitor对象和退出monitor对象来实现的,无论是显式同步还是隐式同步。

synchronized语句块:

1)(使用javap -c 类名)将class文件反编译后可以看到:同步块的入口位置和出口位置(方法结束处和异常处)分别插入了monitorenter字节码指令和monitorexit字节码指令,故同步代码块属于显示同步。

2)线程执行到monitorenter指令时,尝试获取对象的锁。

synchronized方法:

1)JVM从Class文件中的方法结构(method_info)中的 ACC_SYNCHRONIZED 访问标志区分一个方法是否为同步方法,故同步方法属于隐式同步。

2)当方法调用时,调用指令会检查方法的ACC_SYNCHRONIZED访问标志是否被设置,如果设置了,执行线程将先持有monitor,然后再执行方法,最后在方法完成时释放monitor。

3)在方法执行期间,其它线程无法获取该monitor。

4)如果一个同步方法执行期间抛出了异常,并且在方法内部无法处理此异常,那这个同步方法所持有的monitor将在异常抛到同步方法之外时自动释放。

method_info 结构格式如下(java虚拟机规范中的摘录):

method_info {

u2 access_flags;// 用于定义当前方法的访问权限和基本属性的标志

u2 name_index;

u2 descriptor_index;

u2 attributes_count;

attribute_info attributes[attributes_count];

}

method_info结构中访问标记(access_flags)的取值:

标记名值说明

ACC_PUBLIC0x0001public,方法可以从包外访问

ACC_PRIVATE0x0002 private,方法只能本类中访问

ACC_PROTECTED0x0004 protected,方法在自身和子类可以访问

ACC_STATIC0x0008 static,静态方法

ACC_FINAL0x0010 final,方法不能被重写

ACC_SYNCHRONIZED0x0020 synchronized,方法由monitor同步

...

获取锁和释放锁的内存原语:

当线程获取锁时,JMM会把该线程对应的本地内存置为无效。从而使得被monitor保护的临界区代码必须从主内存中读取共享变量。

当线程释放锁时,JMM会把该线程对应的本地内存中的共享变量刷新到主内存中

即:

1将本地内存中的数据设置为无效,

2从主内存中将数据复制到本地内存中,

3在本地内存中进行操作,

4操作完成后将本地内存中的数据刷新到主内存中。整体看起来就像是直接在主内存中操作一样。

synchronized的可重入性:

1)当一个线程再次请求自己持有对象锁的临界资源时,这种情况属于重入锁,请求将会成功。

2)由于synchronized是基于monitor实现的,故每次重入,monitor中的计数器仍会加1。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值