Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >synchronized关键字

synchronized关键字

作者头像
黑洞代码
发布于 2021-03-01 09:11:03
发布于 2021-03-01 09:11:03
40900
代码可运行
举报
运行总次数:0
代码可运行

除夕快乐

说一说对synchronized关键字的理解?

synchronized 关键字解决的是多个线程之间访问资源的同步性,synchronized关键字可以保证被它修饰的方法或者代码块在任意时刻只能有一个线程执行。

另外,在 Java 早期版本中,synchronized 属于重量级锁,效率低下。

因为监视器锁(monitor)是依赖于底层的操作系统的 Mutex Lock 来实现的,Java的线程是映射到操作系统的原生线程之上的。如果要挂起或者唤醒一个线程,都需要操作系统帮忙完成,而操作系统实现线程之间的切换时需要从用户态转换到内核态,这个状态之间的转换需要相对比较长的时间,时间成本相对较高。

庆幸的是在 Java 6 之后 Java 官方对从 JVM 层面对 synchronized 较大优化,所以现在的 synchronized 锁效率也优化得很不错了。JDK1.6 对锁的实现引入了大量的优化,如自旋锁、适应性自旋锁、锁消除、锁粗化、偏向锁、轻量级锁等技术来减少锁操作的开销。

所以,你会发现目前的话,不论是各种开源框架还是 JDK 源码都大量使用了 synchronized 关键字。

说说自己是怎么使用 synchronized 关键字

synchronized 关键字最主要的三种使用方式:

1.修饰实例方法

作用于当前对象实例加锁,进入同步代码前要获得 当前对象实例的锁

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
synchronized void method() {
  //业务代码
}

2.修饰静态方法

也就是给当前类加锁,会作用于类的所有对象实例 ,进入同步代码前要获得 当前 class 的锁。因为静态成员不属于任何一个实例对象,是类成员( static 表明这是该类的一个静态资源,不管 new 了多少个对象,只有一份)。所以,如果一个线程 A 调用一个实例对象的非静态 synchronized 方法,而线程 B 需要调用这个实例对象所属类的静态 synchronized 方法,是允许的,不会发生互斥现象,因为访问静态 synchronized 方法占用的锁是当前类的锁,而访问非静态 synchronized 方法占用的锁是当前实例对象锁。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
synchronized void staic method() {
  //业务代码
}

3.修饰代码块

指定加锁对象,对给定对象/类加锁。synchronized(this|object) 表示进入同步代码库前要获得给定对象的锁。synchronized(类.class) 表示进入同步代码前要获得 当前 class 的锁

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
synchronized(this) {
  //业务代码
}

总结

  1. synchronized 关键字加到 static 静态方法和 synchronized(class) 代码块上都是是给 Class 类上锁。
  2. synchronized 关键字加到实例方法上是给对象实例上锁。
  3. 尽量不要使用 synchronized(String a) 因为 JVM 中,字符串常量池具有缓存功能!

下面我以一个常见的面试题为例讲解一下 synchronized 关键字的具体使用。

面试中面试官经常会说:“单例模式了解吗?来给我手写一下!给我解释一下双重检验锁方式实现单例模式的原理呗!”

双重校验锁实现对象单例(线程安全)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class Singleton {

    private volatile static Singleton uniqueInstance;

    private Singleton() {
    }

    public  static Singleton getUniqueInstance() {
       //先判断对象是否已经实例过,没有实例化过才进入加锁代码
        if (uniqueInstance == null) {
            //类对象加锁
            synchronized (Singleton.class) {
                if (uniqueInstance == null) {
                    uniqueInstance = new Singleton();
                }
            }
        }
        return uniqueInstance;
    }
}

另外,需要注意 uniqueInstance 采用 volatile 关键字修饰也是很有必要。

uniqueInstance 采用 volatile 关键字修饰也是很有必要的, uniqueInstance = new Singleton(); 这段代码其实是分为三步执行:

  1. 为 uniqueInstance 分配内存空间
  2. 初始化 uniqueInstance
  3. 将 uniqueInstance 指向分配的内存地址

但是由于 JVM 具有指令重排的特性,执行顺序有可能变成 1->3->2。指令重排在单线程环境下不会出现问题,但是在多线程环境下会导致一个线程获得还没有初始化的实例。例如,线程 T1 执行了 1 和 3,此时 T2 调用 getUniqueInstance() 后发现 uniqueInstance 不为空,因此返回 uniqueInstance,但此时 uniqueInstance 还未被初始化。

使用 volatile 可以禁止 JVM 的指令重排,保证在多线程环境下也能正常运行。

构造方法可以使用 synchronized 关键字修饰么?

构造方法不能使用 synchronized 关键字修饰。构造方法本身就属于线程安全的,不存在同步的构造方法一说。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-02-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 落叶飞翔的蜗牛 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
synchronized 关键字
synchronized关键字解决的是多个线程之间访问资源的同步性,synchronized关键字可以保证被它修饰的方法或者代码块在任意时刻只能有一个线程执行。
崔笑颜
2020/06/08
4450
synchronized 关键字
早期版本中,synchronized 属于重量级锁,效率低下,这是由于监视器锁(monitor)是依赖于底层操作系统的 Mutex Lock 来实现的,Java 的线程是映射到操作系统的原生线程之上。如果要挂起或者唤醒线程,都需要操作系统帮忙完成,而操作系统进行线程间的切换时,需要从用户态转换到内核态,这个状态的转换需要相对长的时间,时间成本较高,这也就是早期 synchronized 效率低下的主要原因。庆幸的是,Java1.6 以后官方对 synchronized 做了较大的优化,因此现在的 synchronized 锁效率也是比较高的(推荐先使用)。
happyJared
2019/07/03
4580
是时候来唠一唠synchronized关键字了,Java多线程的必问考点!
在之前的博文中,我们介绍了volatile关键字,Java中的锁以及锁的分类,今天我们花5分钟时间,一起学习一下另一个关键字:synchronized。
JavaBuild
2024/05/27
2290
是时候来唠一唠synchronized关键字了,Java多线程的必问考点!
【设计模式】单例
私有构造函数保证了不能通过构造函数来创建对象实例,只能通过公有静态函数返回唯一的私有静态变量。
瑞新
2020/07/07
2890
值得保存的 synchronized 关键字总结
本文是对 synchronized 关键字使用、底层原理、JDK1.6之后的底层优化以及和ReenTrantLock对比做的总结。如果没有学过 synchronized 关键字使用的话,阅读起来可能比较费力。两篇比较基础的讲解 synchronized 关键字的文章:
用户2164320
2018/09/07
4120
synchronized与volatile关键字的实现原理
synchronized修饰于代码片段和静态方法,对于带代码片段或者非静态方法,synchronized是通过头对象中的MarkWord的信息来判断,MarkWord中有锁的类型,锁的地址等信息,对于静态方法,通过.Class文件来判断是否加锁.
天下之猴
2024/09/18
1380
【纯干货】Java 并发进阶常见面试题总结
synchronized关键字解决的是多个线程之间访问资源的同步性,synchronized关键字可以保证被它修饰的方法或者代码块在任意时刻只能有一个线程执行。
乔戈里
2019/12/02
3710
【纯干货】Java 并发进阶常见面试题总结
2019秋招:460道Java后端面试高频题答案版【模块三:Java并发】
Java 并发是 Java 后端开发面试中最重要的模块之一,毕竟这是对 Java 基础的深度考核。而且现在基本上程序都是需要使用多线程进行处理的,如果说 Java 并发你不会,只要面试官问你了,可以说很难通过面试。所以这一块一定要好好下功夫。我个人学习这块知识点的学习方法和 Java集合类是非常像的,重点都在于考察你对源码的了解,学习Java 并发其实就是学习 JUC 包中的一些关键的类:AQS、原子类等等。
乔戈里
2019/09/24
8260
2019秋招:460道Java后端面试高频题答案版【模块三:Java并发】
JUC并发编程之Synchronized关键字详解
在多线程中,有可能会出现多个线程同时访问同一个共享、可变资源的情况,这个资源我们称之其为临界资源;这种资源可能是:对象、变量、文件等。
黎明大大
2021/07/23
3900
JUC并发编程之Synchronized关键字详解
【Java】Synchronized 关键字
His flower had told him that she was only one of her kind in all universe. And here were five thousand of them, all alike, in one single garden!
JuneBao
2022/10/26
3410
【Java】Synchronized 关键字
【Java后端面试经历】我和阿里面试官的“又”一次“邂逅”(附问题详解)
承接上一篇深受好评的文章:《【Java 大厂真实面试经历】我和阿里面试官的一次“邂逅”(附问题详解)》 。时隔 n 个月,又一篇根据读者投稿的《5 面阿里,终获 offer》改编的 “Java 大厂真实面试经历” 文章来啦!希望这样形式的文章,你们能够喜欢,也希望你们可以从这篇文章中切实学到东西。
Guide哥
2020/06/01
1.1K0
【Java后端面试经历】我和阿里面试官的“又”一次“邂逅”(附问题详解)
synchronized 与多线程的哪些关系
JVM 实现的 synchronized JDK 实现的 ReentrantLock
BUG弄潮儿
2022/06/30
2840
synchronized 与多线程的哪些关系
Java内存模型中的volatile和synchronized关键字
这个例子中,counter是一个共享资源,初始值为0。线程t1负责递增counter的值,线程t2负责递减counter的值。通过synchronized关键字对increment()和decrement()方法进行同步,保证在任意时间点只有一个线程可以访问这两个方法,避免了并发问题。最终输出结果为0。
一凡sir
2023/08/22
2310
Java内存模型中的volatile和synchronized关键字
【设计模式自习室】透彻理解单例模式
对于系统中的某些类来说,只有一个实例很重要。比如大家熟悉的Spring框架中,Controller和Service都默认是单例模式。
Rude3Knife的公众号
2019/12/31
4530
【设计模式自习室】透彻理解单例模式
深入理解synchronized底层原理,一篇文章就够了!
如果某一个资源被多个线程共享,为了避免因为资源抢占导致资源数据错乱,我们需要对线程进行同步,那么synchronized就是实现线程同步的关键字,可以说在并发控制中是必不可少的部分,今天就来看一下synchronized的使用和底层原理。 一、synchronized的特性
挨踢小子部落阁
2019/07/16
8710
并发编程-synchronized关键字大总结
可重入(可以避免死锁、单个线程可以重复拿到某个锁,锁的粒度是线程而不是调用)、不可中断(其实也就是上面的原子性)
Wizey
2019/02/26
3610
【java基础】synchronized,volatile,transient关键字的作用
《编程思想之多线程与多进程(1)——以操作系统的角度述说线程与进程》一文详细讲述了线程、进程的关系及在操作系统中的表现,这是多线程学习必须了解的基础。
用户5640963
2019/07/26
1.1K0
【java基础】synchronized,volatile,transient关键字的作用
使用 Synchronized 关键字
使用 Synchronized 关键字来解决并发问题是最简单的一种方式,我们只需要使用它修饰需要被并发处理的代码块、方法或字段属性,虚拟机自动为它加锁和释放锁,并将不能获得锁的线程阻塞在相应的阻塞队列上。
Single
2018/09/27
4590
使用 Synchronized 关键字
深入理解单例模式
Java面试通关手册(Java学习指南,欢迎Star,会一直完善下去,欢迎建议和指导):https://github.com/Snailclimb/Java_Guide
用户2164320
2018/06/14
6200
synchronized的简单理解
synchronized是Java中解决并发问题的一种最常用的方法,也是最简单的一种方法。它能够保证在同一时刻,被修饰的代码块或方法只会有一个线程执行,以达到保证并发安全的效果。
默 语
2024/11/20
2550
synchronized的简单理解
相关推荐
synchronized 关键字
更多 >
交个朋友
加入腾讯云官网粉丝站
蹲全网底价单品 享第一手活动信息
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验