本篇文章为你整理了万字干货(万字干货,房地产开发商破产)的详细内容,包含有万字干货 光 万字干货,房地产开发商破产 万字文字 《万字(卍)》 万字干货,希望能帮助你了解 万字干货。
目录前言线程安全什么是synchronized关键字?synchronized实现方式1.修饰实例方法2.修饰静态方法3.修饰代码块synchronized关键字底层原理synchronized修饰实例方法monitor锁是什么?Java对象内存布局synchronized修饰代码块锁优化自旋锁锁粗化锁消除锁膨胀偏向锁轻量级锁synchronized关键字实现单例模式synchronized 和 volatile 的区别?尾语
作者:小牛呼噜噜 https://xiaoniuhululu.com
计算机内功、JAVA底层、面试、职业成长相关资料等更多精彩文章在公众号「小牛呼噜噜」
大家好,我是呼噜噜,在之前的文章中https://mp.weixin.qq.com/s/0Ii636KQ9sWwX-OhdlPIYw,我们知道了volatile关键字可以保证可见性、有序性,但无法保证原子性的。今天我们来聊聊synchronized关键字,其可以同时保证三者,实现线程安全。
在介绍synchronized关键字之前,我们得强调一下什么是线程安全,所谓线程安全:
当多个线程同时访问一个对象时, 如果不用考虑这些线程在运行时环境下的调度和交替执行, 也不需要进行额外的同步, 或者在调用方进行任何其他的协调操作, 调用这个对象的行为都可以获得正确的结果, 那就称这个对象是线程安全的。
什么是synchronized关键字?
在 Java 早期版本中,synchronized 属于 重量级锁,效率低下;不过在 Java 6 之后,Java 官方对从 JVM 层面对 synchronized 较大优化,所以现在的 synchronized 锁效率也优化得非常不错。目前不论是各种开源框架还是 JDK 源码都大量使用了 synchronized 关键字
synchronized实现方式
synchronized的使用其实比较简单,可以用它来修饰实例方法和静态方法,也可以用来修饰代码块。我们需要注意的是synchronized是一个对象锁,也就是它锁的是一个对象。我们无论使用哪一种方法,synchronized都需要有一个锁对象
修饰实例方法
修饰静态方法
修饰代码块
1.修饰实例方法
synchronized修饰实例方法, 在方法上加上synchronized关键字即可。
public class SynchronizedTest1 {
public synchronized void test() {
System.out.println("synchronized 修饰 方法");
此时,synchronized加锁的对象就是这个方法所在实例的本身,作用于当前实例加锁,进入同步代码前要获得**当前实例的锁 **。
补充一个常见的面试题:构造方法可以用synchronized关键字修饰吗?
不能,也不需要,因为构造方法本身就是线程安全的
2.修饰静态方法
synchronized修饰静态方法的使用与实例方法并无差别,在静态方法上加上synchronized关键字即可
public static synchronized void test(){
i++;
由于静态方法不属于任何一个实例对象,归整个类所有,不依赖于类的特定实例,被类的所有实例共享。给静态方法加synchronized锁,会作用于类的所有对象实例 ,进入同步代码前要获得 当前静态方法所在类的Class对象的锁。
有一点我们需要知道:如果一个线程 A 调用一个实例对象的非静态 synchronized 方法,而线程 B 需要调用这个实例对象所属类的静态 synchronized 方法,是允许的,不会发生互斥现象,因为访问静态 synchronized 方法占用的锁是当前类的锁,而访问非静态 synchronized 方法占用的锁是当前实例对象锁。
3.修饰代码块
synchronized修饰代码块需要传入一个对象。
public class SynchronizedTest2 {
public void test() {
synchronized (this) {
System.out.println("synchronized 修饰 代码块");
此时synchronized加锁对象即为传入的这个对象实例,指定加锁对象,进入同步代码库前要获得给定对象的锁
需要注意的是这里的this:
synchronized(object) ,表示进入同步代码库前要获得 给定对象的锁
synchronized(类.class) ,表示进入同步代码前要获得 给定 Class 的锁
最好不要使用 synchronized(String a) ,因为在 JVM 中,字符串常量池具有缓存功能,如果我们多次加锁,会加锁在同一个对象上
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。