ps:最近一直在面试,Synchronized被问到的挺多的,分三个方面总结下,有不对的地方也请大家指正出来。
-
Synchronized作用:
Synchronized的主要作用是为了保证多线程环境下的线程的安全性,它是一种悲观锁的实现机制。
大家也可以这样理解:现在有一群人都要去上公共厕所,但是坑位只有一个,那谁先上呢?那当然是谁先抢到谁先上啦,但是这个厕所没门碰巧又有两个人同时挤了进去(尴尬不)。这两个人想,这都进去了也不能大眼瞪小眼啊,事还是要办的啊!于是这两个人协商一人用马桶一秒钟再用纸,然后换下一个人,起初还没啥问题,但是用着用着发现纸只剩一片了。于是一个人对另一个人说我用纸,你用手吧(嘿嘿,作者的恶趣),然后这两个人为了这片纸在厕所干了起来。后来厕所管理员为了防止以后这样的事情再发生就在厕所装了门。
言归正传:上面的小事例中一群人就相当于在高并发情况下的多线程环境,公共厕所就是我们要获取的资源(又称临界资源),正是因为这个资源是共享的,如果不加以限制的话多线程环境下就有可能出现你使用的资源是别人修改过的,这样的话线程就不是安全的了,为了保证线程的安全性,所以后面管理员在厕所上安了门,这里的门的作用和Synchronized作用类似,只要我进去了,我就给门反锁上,不管你外面是不是敲的锣鼓震天响,只要我没用完,您~ 就~ 甭~ 想~ 用~ 。
-
Synchronized用法
- Synchronized可修饰方法锁的是当前的对象
- Synchronized可以修饰静态方法锁的是当前类
- Synchronized可以修饰代码块锁的是:你想锁啥锁啥。(有些资源是不能当锁的,这个可以自行百度)
也可以看下:https://blog.youkuaiyun.com/LRBrZero/article/details/105825083
-
Synchronized原理
敲黑板,敲黑板,下面的才是重点,下面的才是重点(上面的都是毛,下面的才是肉)
Synchronized的底层实现是基于JVM,(java 虚拟机)所以要看源码的话,就要看字节码文件。(童鞋:“哎呀,老师我不会啊!”,老师:“嗯,正常”。os:我TM也不会啊,但是面试的时候会问啊!(泪目))。
在了解Synchronized底层原理之前你需要先了解下 Java对象的内存布局 (ps:关于内存布局的知识都来自《深入理解java 虚拟机》P 47 这本书)。
Java 内存布局分为3个区域:对象头(Header),实例数据(Instance Data 干哈的自己去看,不写了),对齐填充(Paddiing 干哈的自己去看,不写了)
对象头包括两部分内容:Mark Word 和 类型指针
1.Mark Word :主要存对象自身的运行时数据,如HashCode,GC分代年龄,锁状态标识,偏向线程ID 等(特别重要)。
2.类型指针:对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。
OK,甜点吃完了,开始吃正餐。
Synchronized 修饰同步代码块:
public class SynchronizedDemo {
public void method() {
synchronized (this) {
System.out.println("synchronized 代码块");
}
}
}

图片代码均出自:https://snailclimb.gitee.io/javaguide-interview
Synchronized 锁同步代码块的锁实现是基于monitor对象,monitor 对象存在于对象的对象头中。
1.monitorenter 指令指向同步代码块的开始位置,monitorexit 指令则指明同步代码块的结束位置。
2.当线程执行monitorenter 指令时会先判断Mark Word的锁标识状态是不是0,0的话标识该资源还没有被其他资源占用,线程 获取后会给锁标识状态变成1,当前线程就是该资源的Owner,其他线程要想获取该资源就必须等待当前线程释放该资源。
3.执行 monitorexit 指令后,将锁计数器设为0,表明锁被释放。
Synchronized 修饰方法:
public class SynchronizedDemo2 {
public synchronized void method() {
System.out.println("synchronized 方法");
}
}

synchronized 使用的是 ACC_SYNCHRONIZED 标识,该标识证明了该方法是一个同步方法,JVM 通过该 ACC_SYNCHRONIZED 访问标志来辨别一个方法是否声明为同步方法,从而执行相应的同步调用。
本文深入解析Synchronized锁在多线程环境下的作用、用法及底层实现原理,通过生动的例子说明其如何保证线程安全性,适合Java开发者阅读。

被折叠的 条评论
为什么被折叠?



