当前位置: 首页 > news >正文

synchronized 与 volatile 关键字

目录

  • 1.前言
  • 1.synchronized 关键字
    • 1. 互斥
    • 2.保证内存可见性
    • 3.可重入
  • 2. volatile 关键字
    • 1.保证内存可见性
    • 2.无法保证原子性
  • 3.synchronized 与 volatile 的区别

1.前言

  synchronized关键字和volatile是大家在Java多线程学习时接触的两个关键字,很多同学可能学习完就忘记了,本文帮助大家回顾以及学习两个关键字的作用,以及说出它们的区别,同时也为了自己学习巩固。

1.synchronized 关键字

1. 互斥

  属于synchronized最关键的特性,可以起到互斥的作用,当某个线程执行到某个对象的synchronized中时,其他线程如果也执行到同一个对象synchronized 时就会进行阻塞等待

  • 进入synchronized 修饰的代码块此时相当于 加锁
  • 退出synchronized 修饰的代码块此时相当于 释放锁

其解决的问题是在多线程环境下,多个线程对于同一个变量进行读写操作时可能产生的线程安全问题。
如下图代码:

public class Main {static int count = 0;static void add() {count++;}public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {for (int i = 0; i < 50000; i++) {add();}});Thread t2 = new Thread(() -> {for (int i = 0; i < 50000; i++) {add();}});t1.start();t2.start();t1.join();t2.join();System.out.println(count);}
}

按照预期,我们希望count的值应该是100000,当执行后输出的答案却是:
在这里插入图片描述
无论多次执行多少次,答案总是与预期相差甚远。这是最简单的多线程安全问题。因为count++这个操作,需要先将count从主内存读入到工作内存,然后增值,再将更改后的值写回主内存,这一系列操作必须保证原子性,而在多线程环境下是无法保证的,所以我们需要加上synchronized进行上锁,以此保证自增这个操作的原子性。
只需更改add方法如下:

 synchronized static void add() {count++;}

再次运行后答案与预期相符合:
在这里插入图片描述
需要注意一点,synchronized修饰方法时如果是静态方法,则加的是该类对象的锁,如果是成员方法,则加的是对象锁。

2.保证内存可见性

从上面也可以看出synchronized的工作过程:

  • 1.获得互斥锁
  • 2.从主内存拷贝变量的最新副本到工作内存
  • 3.执行代码
  • 4.讲更改后的共享变量的值更新回工作内存
  • 5.释放互斥锁

这样的工作流程,是一定可以保证内存可见性的。当然有的同学并不了解什么是内存可见性,下文讲volatile时我们稍微讲一下,因为它也能保证内存可见性。

3.可重入

synchronized同步块,对于同一条线程来说是可重入的,不会出现将自身锁死的情况。

当然大家可能对 自身锁死 这个情况不太理解,我们举例一个代码:

public class Main {//锁对象public static Object lock = new Object();public static void main(String[] args) {//一次加锁synchronized (lock) {//二次加锁synchronized (lock) {System.out.println("正确输出");}}}
}

当线程在一次加锁时,会成功加锁,当第二次加锁时,此时lock已被上锁,于是该线程进行阻塞等待,但其实这个锁是被它自己拿着的,它又不进行释放锁操作,于是将自己锁死。这样的锁称之为 不可重入锁

当我们Java中的synchronized是可重入锁,不会出现上面的问题,它可以正确打印:
在这里插入图片描述
如果对上述代码还不够理解,可以再看一个二次加锁的例子:

public class Main {public int count = 0;synchronized void increase() {count++;}synchronized void increase2() {increase();}
}

在上诉代码中:

  • increaseincrease2两个方法都加了synchronized ,而且它们的锁对象都是针对当前对象加锁的。
  • 在调用increase2时,会先给该对象上锁,执行调用increase时,会二次上锁(此时上个锁还未释放),这是没问题的,因为synchronized可重入锁

那是否真的上了两把锁呢?
其实并非如此,在可重入锁的内部,包含了 线程持有者计数器 两个信息。

  • 如果某个线程加锁时,发现锁已被占用,但又发现占用的恰好是自己时,那么然后可以获取到这个锁,并让计数器自增
  • 解锁时首先会让计数器自减,但只有真正自减到0时,我们才会真正意义上的将该锁释放,以供其他线程获取到。

2. volatile 关键字

相对于 synchronized来说,大家可能对volatile会比较陌生,我们来看看其有哪些作用。

1.保证内存可见性

在这里插入图片描述
简单来说,线程在工作时,会去主内存中读取数据到工作内存中,然后从工作内存读取数据。但是,线程从工作内存读取数据的速度,要远远的大于从主内存读取数据。

当一个线程大量地从主内存请求同一个变量的值时,它会发现这个值一直没变,此时jvm会 “自作主张” 的进行优化,直接从工作内存读取之前读到的值。这就会导致一个问题,其他线程对这个共享变量值进行修改,这个线程不能及时地被看到,也就读到了一个错误的值。

比如如下代码:

public class Main{static int isQuit = 0;public static void main(String[] args) {Thread t = new Thread(() -> {while (isQuit == 0) {}System.out.println("t线程执行结束");});t.start();Scanner sc = new Scanner(System.in);isQuit = sc.nextInt();System.out.println("main线程执行结束");}
}

执行以后随便输入一个非零整数:
在这里插入图片描述
发现t线程仍然在进行,而main线程已经结束,但按照逻辑其实此时isQuit值被修改为非零,t线程也应该结束。这就是由于内存可见性产生的问题,main线程修改了isQuit的值t线程并不能及时的接收到。

解决的方法也很简单,只需要给isQuit加上volatile关键字,这样每次t线程都会强制去主内存中读取isQuit的值,从而保证了内存可见性。

2.无法保证原子性

  volatile相较于synchronized来说,主要在于其无法保证原子性,也就是对于下面这个程序,即使给count加上volatile,我们也无法让count的值为100000

public class Main {static int count = 0;static void add() {count++;}public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {for (int i = 0; i < 50000; i++) {add();}});Thread t2 = new Thread(() -> {for (int i = 0; i < 50000; i++) {add();}});t1.start();t2.start();t1.join();t2.join();System.out.println(count);}
}

3.synchronized 与 volatile 的区别

  根据上面的总结,我们可知:synchronized既可以保证原子性还可以保证内存可见性,而volatile只能保证内存可见性。那有的人是不是肯定想,那我们无脑使用synchronized不就好了吗?
  那肯定不对,synchronized会进行加锁,使得效率大大的较低,而volatile却不会影响效率,所以只有必须要保证原子性的操作,我们才选择synchronized进行加锁。

相关文章:

synchronized 与 volatile 关键字

目录1.前言1.synchronized 关键字1. 互斥2.保证内存可见性3.可重入2. volatile 关键字1.保证内存可见性2.无法保证原子性3.synchronized 与 volatile 的区别1.前言 synchronized关键字和volatile是大家在Java多线程学习时接触的两个关键字&#xff0c;很多同学可能学习完就忘记…...

【0成本搭建个人博客】——Hexo+Node.js+Gitee Pages

目录 1、下载安装Git 2、下载安装Node.js 3、使用Hexo进行博客的搭建 4、更改博客样式 5、将博客上传到Gitee 6、更新博客 首先看一下Hexo的博客的效果。 1、下载安装Git Git 是一个开源的分布式版本控制系统&#xff0c;可以有效、高速地处理从很小到非常大的项目版本…...

【面试实战】认证授权流程及原理分析

认证授权流程及原理分析 1、认证 (Authentication) 和授权 (Authorization)的区别是什么?2、什么是Cookie ? Cookie的作用是什么?如何在服务端使用 Cookie ?3、Cookie 和 Session 有什么区别?如何使用Session进行身份验证?1、认证 (Authentication) 和授权 (Authorizatio…...

TPM命令解析之tpm2_startauthsession

参考网址链接&#xff1a;tpm2-tools/tpm2_startauthsession.1.md at master tpm2-software/tpm2-tools GitHub 命令名称 tpm2_startauthsession 功能 启动一个TPM会话。 命令形式 tpm2_startauthsession [OPTIONS] 描述 启动一个TPM会话。默认是启动一个试验&#xff08…...

第14章 局部波动率模型

这学期会时不时更新一下伊曼纽尔德曼&#xff08;Emanuel Derman&#xff09; 教授与迈克尔B.米勒&#xff08;Michael B. Miller&#xff09;的《The Volatility Smile》这本书&#xff0c;本意是协助导师课程需要&#xff0c;发在这里有意的朋友们可以学习一下&#xff0c;思…...

云原生周刊:开源“赢了”,但它可持续吗?

日前召开的 State of Open 会议上&#xff0c;开源“赢了”&#xff0c;但如果政府和企业不站出来确保生态系统在未来的弹性和可持续性&#xff0c;那么它仍然会失败。 OpenUK 首席执行官 Amanda Brock 在开幕式上表示&#xff0c;数字化和开源在过去 5 到 10 年的进步提升了工…...

读《企业IT架构转型之道》

本书还没读完&#xff0c;暂摘抄一些概念&#xff0c;因为自身做的新系统也在转型&#xff0c;从单体式到一体化一年来遇到很多问题有技术上的&#xff0c;也有团队协作的&#xff0c;过程是痛苦且复杂的&#xff0c;所以在刚翻阅前几十页时候&#xff0c;对于淘宝技术团队转型…...

Qt中的QTcpSocket、QWebSocket和QLocalSocket

同时实现了QTcpSocket、QWebSocket和QLocalSocket的简单通讯deamon&#xff0c;支持自动获取本机ip&#xff0c;多个客户端交互。在这个基础上你可以自己加错误检测、心跳发送、包封装解析和客户端自动重连等功能。 获取本机电脑ip&#xff1a; QString Widget::getIp() {QSt…...

枚举学习贴

1. 概述 1.1 是什么 枚举对应英文(enumeration, 简写 enum)枚举是一组常量的集合。可以这里理解&#xff1a;枚举属于一种特殊的类&#xff0c;里面只包含一组有限的特定的对象 1.2 枚举的二种实现方式 自定义类实现枚举使用 enum 关键字实现枚举 1.3 什么时候用 存在有限…...

【C++】30h速成C++从入门到精通(继承)

继承的概念及定义继承的概念继承&#xff08;inheritance&#xff09;机制是面向对象程序设计使代码可以复用的重要手段&#xff0c;它允许程序员在保持原有类特性的基础上进行扩展&#xff0c;增加功能&#xff0c;这样产生新的类&#xff0c;称派生类。继承呈现了面向对象程序…...

Java多线程还不会的进来吧,为你量身打造

&#x1f497;推荐阅读文章&#x1f497; &#x1f338;JavaSE系列&#x1f338;&#x1f449;1️⃣《JavaSE系列教程》&#x1f33a;MySQL系列&#x1f33a;&#x1f449;2️⃣《MySQL系列教程》&#x1f340;JavaWeb系列&#x1f340;&#x1f449;3️⃣《JavaWeb系列教程》…...

8 神经网络及Python实现

1 人工神经网络的历史 1.1 生物模型 1943年&#xff0c;心理学家W.S.McCulloch和数理逻辑学家W.Pitts基于神经元的生理特征&#xff0c;建立了单个神经元的数学模型&#xff08;MP模型&#xff09;。 1.2 数学模型 ykφ(∑i1mωkixibk)φ(WkTXb)y_{k}\varphi\left(\sum_{i1…...

使用QIS(Quantum Image Sensor)图像重建总结(1)

最近看了不少使用QIS重建图像的文章&#xff0c;觉得比较完整详细的还是Abhiram Gnanasambandam的博士论文&#xff1a;https://hammer.purdue.edu/articles/thesis/Computer_vision_at_low_light/20057081 1 介绍 讲述了又墨子的小孔成像原理&#xff0c;到交卷相机&#xf…...

【SpringCloud】SpringCloud教程之Nacos实战(二)

目录前言一.Nacos实现配置管理二.Nacos拉取配置三.Nacos配置热更新(自动刷新&#xff0c;不需要重启服务)1.在有Value注入变量所在类添加注解2.新建类用于属性加载和配置热更新四.Nacos多环境配置共享1.多环境共享配置2.配置的加载优先级测试3.配置优先级前言 Nacos实战一&…...

利用Qemu工具仿真ARM64平台

Windows系统利用Qemu仿真ARM64平台0 写在最前1 Windows安装Qemu1.1 下载Qemu1.2 安装Qemu1.3 添加环境变量1.4测试安装是否成功2. Qemu安装Ubuntu-Server-Arm-642.1 安装前的准备2.2 安装Ubuntu server arm 64位镜像3 Windows配置Qemu网络和传输文件3.1 参考内容3.2 Windows安装…...

【Hello Linux】进程控制 (内含思维导图)

作者&#xff1a;小萌新 专栏&#xff1a;Linux 作者简介&#xff1a;大二学生 希望能和大家一起进步&#xff01; 本篇博客简介&#xff1a;简单介绍下进程的控制 包括进程启动 进程终止 进程等待 进程替换等概念 进程控制介绍进程创建fork函数fork函数的返回值fork函数的使用…...

嵌入式linux物联网毕业设计项目智能语音识别基于stm32mp157开发板

stm32mp157开发板FS-MP1A是华清远见自主研发的一款高品质、高性价比的Linux单片机二合一的嵌入式教学级开发板。开发板搭载ST的STM32MP157高性能微处理器&#xff0c;集成2个Cortex-A7核和1个Cortex-M4 核&#xff0c;A7核上可以跑Linux操作系统&#xff0c;M4核上可以跑FreeRT…...

【黄河流域公安院校网络空间安全技能挑战赛】部分wp

文章目录webbabyPHPfunnyPHPEzphp**遍历文件目录的类**1、DirectoryIterator&#xff1a;2、FilesystemIterator:3、**Globlterator**读取文件内容的类&#xff1a;SplFileObjectMisc套娃web babyPHP <?php highlight_file(__FILE__); error_reporting(0);$num $_GET[nu…...

五点CRM系统核心功能是什么

很多企业已经把CRM客户管理系统纳入信息化建设首选&#xff0c;用于提升核心竞争力&#xff0c;改善企业市场、销售、服务、渠道和客户管理等几个方面&#xff0c;并进行创新或转型。CRM系统战略的五个关键要点是&#xff1a;挖掘潜在客户、评估和培育、跟进并成交、分析并提高…...

window.print() 前端实现网页打印详解

目录 前言 一、print()方法 二、打印样式 2.1使用打印样式表 2.2使用媒介查询 2.3内联样式使用media属性 2.4在css中使用import引入打印样式表 三、打印指定区域部分内容 3.1方法一 3.2方法二 3.3方法三 四、强制插入分页 4.1page-break-before&#xff08;指定元素前…...

php程序员应具有的7种能力

php程序员应具有什么样的能力&#xff0c;才能更好的完成工作&#xff0c;才会有更好的发展方向呢&#xff1f;在中国我想您不会写一辈子代码的&#xff0c;那样不可能&#xff0c;过了黄金期&#xff0c;您又怎么办呢&#xff1f;看了本文后&#xff0c;希望对您有所帮助。 一…...

quarkus 生产环境与k8s集成总结

quarkus 生产环境与k8s集成总结 大纲 基础准备quarkus2.13.7脚手架工程配置GraalVM-java11 安装配置配置maven3.8.7linux环境下云原生二进制文件打包环境搭建编译运行quarkus二进制文件quarkus二进制文件制作为docker镜像并运行使用k8s部署quarkus二进制文件 基础准备 生产…...

蓝桥杯训练day2

day21.二分(1)789. 数的范围(2)四平方和&#xff08;1&#xff09;哈希表做法&#xff08;2&#xff09;二分做法(3)1227. 分巧克力&#xff08;4&#xff09;113. 特殊排序(5)1460. 我在哪&#xff1f;2.双指针(1)1238. 日志统计(2)1240. 完全二叉树的权值&#xff08;3&#…...

为什么99%的程序员都做不好SQL优化?

连接层 最上层是一些客户端和链接服务&#xff0c;包含本地sock 通信和大多数基于客户端/服务端工具实现的类似于 TCP/IP的通信。主要完成一些类似于连接处理、授权认证、及相关的安全方案。在该层上引入了线程 池的概念&#xff0c;为通过认证安全接入的客户端提供线程。同样…...

Jenkins最新版安装调试

清理旧的jenkins&#xff1a; find / -name jenkins* 一项一项的清理&#xff1a;rm -rf /var/log/jenkins* 下载最新版jenkins镜像&#xff1a;jenkins-redhat-stable安装包下载_开源镜像站-阿里云 上传到服务器&#xff1a; 安装命令&#xff1a; yum install -y jenkins…...

简略说一下go的sync.RWMutex锁

在简略的说之前&#xff0c;首先要对RW锁的结构有一个大致的了解 type RWMutex struct {w Mutex // 写锁互斥锁&#xff0c;只锁写锁&#xff0c;和读锁无关writerSem uint32 // sema锁--用于“写协程”排队等待readerSem uint32 // sema锁--用于“读协程”排队…...

软考马上要报名了,出现这些问题怎么办?

目前&#xff0c;四川、山东、山西、辽宁、河北等地已经率先发布了2023年上半年软考报名通知。 四川&#xff1a;2023年3月13日-4月4日 山东&#xff1a;2023年3月17日9:00-4月3日16:00 山西&#xff1a;2023年3月14日9:00-3月28日11:00 辽宁&#xff1a;2023年3月14日8:30…...

单链表(增删查改)

目录一、什么是单链表&#xff1f;二、单链表的增删查改2.1 结构体变量的声明2.2 申请新结点2.2 链表的头插2.3 链表的尾插2.4 链表的头删2.5 链表的尾删2.6 链表的查找2.7 链表的任意位置后面插入2.8 链表的任意位置后面删除2.9 链表的销毁2.10 链表的打印三、代码汇总3.1 SLi…...

端口复用(bind error: Address already in use 问题)

欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起探讨和分享Linux C/C/Python/Shell编程、机器人技术、机器学习、机器视觉、嵌入式AI相关领域的知识和技术。 端口复用专栏&#xff1a;《Linux从小白到大神》《网络编程》 在前面讲解TCP状态转换中提到过一个2MSL…...

数字化引领乡村振兴,VR全景助力数字乡村建设

一、数字乡村建设加速经济发展随着数字化建设的推进&#xff0c;数字化农业产业正在成为农业产业发展的主导力量&#xff0c;因此数字化技术赋予农业产业竞争力的能力不可小觑。数字化乡村建设背景下&#xff0c;数字化信息技术将全面改造升级农村产业&#xff0c;从农业、养殖…...

电商网站首页怎么制作/今日新闻最新头条

MYSQL数据库设计规范1、数据库命名规范采用26个英文字母(区分大小写)和0-9的自然数(经常不需要)加上下划线_组成;命名简洁明确(长度不能超过30个字符);例如&#xff1a;user, stat, log, 也可以wifi_user, wifi_stat, wifi_log给数据库加个前缀;除非是备份数据库可以加0-9的自然…...

沈阳网站制作找网势科技/平台宣传推广方案

共享打印机作为企业日常OA办公必不可少的设备&#xff0c;我们需要用到的功能包括打印、服务、扫描于一体&#xff0c;甚至还包括传真功能&#xff0c;如何发挥共享打印机的功能呢&#xff1f;我们可以选择激光一体机、多功能复印机这样的设备&#xff0c;由于激光一体机成本比…...

好看的网站后台模板/百度竞价客服

2019独角兽企业重金招聘Python工程师标准>>> IBM常见的java技术面试指导&#xff1a; 1. Spring整合struts有几种方式 2中 把struts的Action托管给spring&#xff0c;和不托管 2. Spring的动态代理是怎么写的? 怎么配置的&#xff1f; 这个问法太笼统&am…...

网站制作收费明细表/百度推广代理商有哪些

前言现在越来越多项目都采用前后端分离模式开发&#xff0c;这样前后端就可以同时开发&#xff0c;而且互不影响。但是目前项目跟进的很紧&#xff0c;没什么时间写后台&#xff0c;但是前端没接口测试可能会隐藏很多bug&#xff0c;到后面再来排查就麻烦了。所以在后端接口没有…...

织梦做的网站如何上线/整合营销理论

一、员工每天都比平常水平好一点点 二、领导力所谓“领导力”&#xff0c;不是“在员工面前摆谱”的能力&#xff0c;更不是给员工添堵的能力。恰恰相反&#xff0c;它是一种“服务员工”的能力&#xff0c;或者再说得明白点儿&#xff0c;是一种“让员工感到舒坦”的能力。为了…...

番禺网站开发哪家专业/朝阳seo排名

1、HBuilder 功能简介&#xff1a; HBuilder是专为前端打造的开发工具&#xff0c;具有飞一样的编码、最全的语法库和浏览器兼容数据、可以方便的制作手机APP、最保护眼睛的绿柔设计等特点。支持HTML、CSS、JS、PHP的快速开发。从开放注册以来深受广大前端朋友们的喜爱。 2、…...