java并发相关(一)—— 一切从synchronized说起

笔者初次接触锁相关知识,是经典的卖票问题中引入了synchronize。

一、synchronize的几种用法:

讲到synchronize,总归逃不开synchronize的几种基本用法:

  • 修饰实例方法
  • 修饰代码块(修饰对象、类)
  • 修饰静态方法

下面我们就此逐一讲解:

synchronize修饰实例方法

  简单来讲,修饰实例方法,其实锁定的是方法所在的实例。

  所以对于同一个java实例,如果用synchronize修饰了方法a与方法b,其实他们使用的是同一把锁。

synchronize修饰代码块

  单纯修饰代码块,同修饰实例方法;

  synchronized(object),修饰对象实例。

  synchronized(a.class),同修饰静态方法。

synchronize修饰静态方法

  修饰静态方法,我们通常称为类锁,然而实际上,类锁也是作为对象锁实现的,这又涉及到jvm的类加载。

  即当jvm加载类文件时,他会加载java.lang.class实例,而实际上类锁就锁在这个实例上。又因为Class的相关数据存储在永久带PermGen(jdk1.8则是metaspace),永久带是全局共享的,因此静态方法锁相当于类的一个全局锁,会锁所有调用该方法的线程;

二、synchronize的底层实现(基础):

说道synchronize的实现,必定绕不开对象在jvm中的布局,直接上图:

 

  • 实例数据:存放类的属性数据信息,包括父类的属性信息,如果是数组的实例部分还包括数组的长度,这部分内存按4字节对齐。

  • 对齐填充:由于虚拟机要求对象起始地址必须是8字节的整数倍。填充数据不是必须存在的,仅仅是为了字节对齐,这点了解即可。

接下来要着重看下java的对象头,这是实现synchronize的基础:

 

其中Mark Word在默认情况下存储着对象的HashCode、分代年龄、锁标记位等以下是32位JVM的Mark Word默认存储结构,结构如下图:

 

 锁的升级机制我们会在下一篇中进行分析,附上链接如下:https://www.cnblogs.com/fbw-gxy/p/11689431.html 

 重量级锁会指向一个Monitor的指针,对于Monitor对象,他是由ObjectMonitor实现,HotSpot中由c++实现,这一点我们会在synchronize的可重入性中分析。

参考文章:

深入理解Java并发之synchronized实现原理:https://blog.csdn.net/javazejian/article/details/72828483#%E7%90%86%E8%A7%A3java%E5%AF%B9%E8%B1%A1%E5%A4%B4%E4%B8%8Emonitor

java 并发编程-volatile、CAS、synchronize:

https://www.cnblogs.com/dosomethingyoulike/p/9344734.html

 

 

 

 

 

 

 

 

posted @ 2019-10-16 23:35  豆豆323  阅读(230)  评论(0编辑  收藏  举报