工作中的点点滴滴-对于锁的一点儿认识

背景

  最近做一个报表,基础数据比较大,然后开了3个线程处理,然后分别向Map里面里面插入数据,这个的Map用的是HashMap,所以为了避免多线程安全性问题。需要在HashMap添加数据的地方要加一个锁。那么有人来说了,你可以用线程安全的CurrentHashMap啊,那你有没有思考过在多线程的环境下CurrentHashMap所有的操作都是安全的吗?这里对CurrentHashMap安不安全先不展开讨论。因为要用到锁,所以绕不过去的肯定就synchronized和ReentrantLock。那这两中锁从实现的方式上有什么不同呢,我们一起来了解一下。

首先来先看synchronized,毕竟使用起来简单嘛哈哈哈哈哈,因为synchronized是jvm里面的一个关键字,所以如果你想通过常规的查看源码的方式来弄明白synchronized估计就不行了。所以我们只能通过jdk自带的工具javap -c [class文件] 来通过字节码分析。

先放上测试代码和他对应的字节码。

1     public void method1() {
2         synchronized (this)
3         {
4 
5         }
6     }

相对于普通方法,我们是不是一眼就可以看出有差别的地方了,那就是在code:5和code:10那里。根据JVM规范要求,当在执行在执行monitorenter指令的时候,首先要去尝试获取对象的锁,如果这个对象没有被锁定,或者当前线程已经拥有了这个对象的锁,就把锁的计数器加1,相应地,在执行monitorexit的时候会把计数器减1,当计数器减小为0时,锁就释放了。

通过字节码我们可以知道synchronized锁执行过程,那他底层是怎么来实现的呢?首先在jvm规范中任何一个对象都由三部分组成的,对象头,数据,填充位。在对象头中又分为两部分,第一部分主要用于储存对象自身的运行时数据,比如hashCode,GC年龄,锁信息等。

 

 

 

对象头的另外一部分是类型执指针,即对象指向他的类元数据的指针。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章