【Java】详解volatile和synchronized关键字

volatilesynchronized都是Java中用于控制并发的关键字,但是它们的使用场景和原理是不同的。

  1. volatile关键字:
    • 特点:volatile关键字主要有两个特性:保证变量的可见性和防止指令重排。当一个共享变量被volatile修饰时,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,它会去内存中读取新值。而普通的共享变量不能保证可见性,因为线程间的共享变量值存在于主存,而每个线程都有自己的工作内存,线程间通信需要通过主存来完成。这可能导致一个线程在主存中修改了一个变量的值,另一个线程还继续使用它在工作内存中的变量值,造成数据的不一致。另外,volatile关键字可以防止指令重排。编译器优化的时候,不能够将其后面的代码排到其前面来执行。当要对一个volatile变量进行写操作时,JMM会先将操作执行,然后再执行volatile写操作,即不会进行指令重排。
    • 优点:volatile相对于synchronized是一种较为轻量级的同步策略,性能开销相对较小,线程访问volatile变量不会被阻塞。
    • 缺点:volatile无法保证复合操作的原子性。例如,count++操作实际上是分为三步执行的:读取count的值,对count加1,将新值写回。
    • 适用场景:当对变量的写入依赖于当前值,例如使用该变量做判断,或者写入的值与当前值无关时,可以使用volatile。例如,一个布尔标记位。
    • 不适用场景:当需要对多个操作进行原子性保证,或者需要对某些方法或者某些代码块进行同步控制的时候,不能够使用volatile
public class VolatileExample {private volatile int counter = 0;public void incrementCounter() {counter++;}public int getCounter() {return counter;}public static void main(String[] args) throws InterruptedException {VolatileExample example = new VolatileExample();Thread thread1 = new Thread(() -> {for (int i = 0; i < 1000; i++) {example.incrementCounter();}});Thread thread2 = new Thread(() -> {for (int i = 0; i < 1000; i++) {example.incrementCounter();}});thread1.start();thread2.start();thread1.join();thread2.join();System.out.println("Counter: " + example.getCounter()); // 输出结果可能小于2000}
}

在上述示例中,尽管使用了volatile关键字,但是incrementCounter()方法并不是线程安全的,因为counter++操作不是原子性的,所以最后输出的结果可能小于2000。

  1. synchronized关键字:
    • 特点:synchronized关键字可以保证代码块或者方法的原子性,即在同一时刻,只有一个线程可以执行synchronized修饰的代码块或者方法。另外,它还可以保证变量的可见性和防止指令重排。当一个线程进入synchronized代码块或者方法时,其他线程不能进入,只有当该线程退出后,其他线程才能进入,这就保证了原子性。当一个线程退出synchronized代码块或者方法时,它对共享变量的修改会立即写入主存,当其他线程进入后,它会从主存读取共享变量的新值,这就保证了可见性。另外,编译器和处理器在执行synchronized代码块或者方法时,不会进行指令重排。
    • 优点:synchronized关键字可以保证代码块或者方法的原子性,可以解决多个线程同时访问共享资源导致的线程安全问题。
    • 缺点:synchronized关键字的性能开销较大,当一个线程进入synchronized代码块或者方法时,其他线程会被阻塞,可能导致线程的阻塞和唤醒带来大量的性能开销。
    • 适用场景:当需要对多个操作进行原子性保证,或者需要对某些方法或者某些代码块进行同步控制的时候,可以使用synchronized
    • 不适用场景:当只需要保证变量的可见性,而不需要保证原子性,或者对性能有较高要求的时候,不适合使用synchronized
public class SynchronizedExample {private int counter = 0;public synchronized void incrementCounter() {counter++;}public int getCounter() {return counter;}public static void main(String[] args) throws InterruptedException {SynchronizedExample example = new SynchronizedExample();Thread thread1 = new Thread(() -> {for (int i = 0; i < 1000; i++) {example.incrementCounter();}});Thread thread2 = new Thread(() -> {for (int i = 0; i < 1000; i++) {example.incrementCounter();}});thread1.start();thread2.start();thread1.join();thread2.join();System.out.println("Counter: " + example.getCounter()); // 输出结果为2000}
}

在上述示例中,使用了synchronized关键字,incrementCounter()方法是线程安全的,因为synchronized关键字保证了counter++操作的原子性,所以最后输出的结果为2000。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/17140.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大数据Flink(五十一):Flink的引入和Flink的简介

文章目录 Flink的引入和Flink的简介 一、Flink的引入 1、第1代——Hadoop MapReduce

CentOS 8 服务器安装 MySQL 报错:no match mysql-community-server

参考 MySQL 官方文档&#xff1a; Re: No match for argument: mysql-community-serverMySQL yum 安装文档 报错如下&#xff1a; 1.No match for argument: mysql-community-server 2.Error: Unable to find a match: mysql-community-server上面的错误都提示找不到 mysql-…

RK809 电源管理芯片配置3-RK3568

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言RK809 芯片概述认识DCDC和LDORK809的引脚RK809 的功能电源管理的概念配置内核驱动电源域IO 电源域配置方法前言 前面提到编译的时候需要正确配置电源,RK3568的电源管理芯片是RK809,下面就来…

MyBatis 核心组件 —— Configuration

概述 Mybatis 的核心组件如下所示&#xff1a; Configuration&#xff1a;用于描述 MyBatis 的主配置信息&#xff0c;其他组件需要获取配置信息时&#xff0c;直接通过 Configuration 对象获取。除此之外&#xff0c;MyBatis 在应用启动时&#xff0c;将 Mapper 配置信息、类…

精选算法题(4)——字符串比较

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 题目描述&#xff1a; 好久没做题目了&#xff0c;近期刷抖音碰到一个题目&#xff0c;乍一看不是很难&#xff0c;但是手生了&a…

HTTP——HTTP报文内的HTTP信息

HTTP 通信过程包括从客户端发往服务器端的请求及从服务器端返回客户端的响应。本章就让我们来了解一下请求和响应是怎样运作的。 HTTP 一、HTTP报文二、请求报文及响应报文的结构三、编码提升传输速率1、报文主体和实体主题的差异2、压缩传输的内容编码3、分割发送的分块传输编…

HCIP——前期综合实验

前期综合实验 一、实验拓扑二、实验要求三、实验思路四、实验步骤1、配置接口IP地址2、交换机配置划分vlan10以及vlan203、总部分部&#xff0c;骨干网配置OSPF分部总部骨干网 4、配置BGP建立邻居关系总部骨干网分部 5、发布用户网段6、将下一跳改为本地7、允许AS重复8、重发布…

【Linux】 UDP网络套接字编程

&#x1f34e;作者&#xff1a;阿润菜菜 &#x1f4d6;专栏&#xff1a;Linux系统网络编程 文章目录 一、网络通信的本质&#xff08;port标识的进程间通信&#xff09;二、传输层协议UDP/TCP认识传输层协议UDP/TCP网络字节序问题&#xff08;规定大端&#xff09; 三、socket编…

前端面试题-react

1 React 中 keys 的作⽤是什么&#xff1f; Keys 是 React ⽤于追踪哪些列表中元素被修改、被添加或者被移除的辅助标识在开发过程中&#xff0c;我们需要保证某个元素的 key 在其同级元素中具有唯⼀性。在 React Diff 算法中 React 会借助元素的 Key 值来判断该元素是新近创建…

第十三章 利用PCA简化数据

文章目录 第十三章 利用PCA简化数据13.1降维技术13.2PCA13.2.1移动坐标轴 13.2.2在NumPy中实现PCA13.3利用PCA对半导体制造数据降维 第十三章 利用PCA简化数据 PCA&#xff08;Principal Component Analysis&#xff0c;主成分分析&#xff09;是一种常用的降维技术&#xff0…

剑指offer41.数据流中的中位数

我一开始的想法是既然要找中位数&#xff0c;那肯定要排序&#xff0c;而且这个数据结构肯定要能动态的添加数据的&#xff0c;肯定不能用数组&#xff0c;于是我想到了用优先队列&#xff0c;它自己会排序都不用我写&#xff0c;所以addNum方法直接调用就可以&#xff0c;但是…

MAC电脑设置charles,连接手机的步骤说明(个人实际操作)

目录 一、charles web端设置 1. 安装charles之后&#xff0c;先安装证书 2. 设置 Proxy-Proxy Settings 3. 设置 SSL Proxying 二、手机的设置 1. 安卓 2. ios 资料获取方法 一、charles web端设置 1. 安装charles之后&#xff0c;先安装证书 Help-SSL Proxying-Inst…

sql group by 加条件

在SQL中&#xff0c;可以在GROUP BY子句中加入条件&#xff0c;以进一步过滤结果。你可以使用HAVING子句来添加条件。HAVING子句的使用方式类似于WHERE子句&#xff0c;但不同的是&#xff0c;它用于对GROUP BY子句生成的分组进行过滤。 以下是一个示例&#xff0c;演示如何在…

优化基于tcp,socket的ftp文件传输程序

原始程序&#xff1a; template_ftp_server_old.py&#xff1a; import socket import json import struct import os import time import pymysql.cursorssoc socket.socket(socket.AF_INET, socket.SOCK_STREAM) HOST 192.168.31.111 PORT 4101 soc.bind((HOST,PORT)) p…

是面试官放水,还是公司实在是太缺人?这都没挂,华为原来这么容易进...

华为是大企业&#xff0c;是不是很难进去啊&#xff1f;” “在华为做软件测试&#xff0c;能得到很好的发展吗&#xff1f; 一进去就有9.5K&#xff0c;其实也没有想的那么难” 直到现在&#xff0c;心情都还是无比激动&#xff01; 本人211非科班&#xff0c;之前在字节和腾讯…

Centos/Ubuntu 替换yum/apt源?

yum/apt源如果不满足要求, 可以考虑将源替换为阿里云的源。 1.CentOS更换阿里云yum源 1. 备份 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base-bak.repo 2. 下载 wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Cent…

iphone卡在恢复模式怎么办?修复办法分享!

iPhone 卡在恢复屏幕问题是 iPhone 用户在软件更新或恢复期间的常见问题。如果你也遇到此问题&#xff0c;不要着急&#xff0c;接下来我们将探讨 iPhone 卡在恢复屏幕上的主要原因&#xff0c;以及如何轻松修复它。 iPhone卡在恢复屏幕问题上没有一个特别的原因&#xff0c;但…

数字资产管理是做什么的?

显然&#xff0c;单纯依靠人力来管理和盘点固定资产已经不能满足公司日益增长的需求。合理使用固定资产管理系统来帮助管理实物资产已经成为一种趋势。  有鉴于此&#xff0c;依靠信息技术的支持&#xff0c;选择RFID固定资产管理系统可以有效解决资产管理盘点等难题&#xf…

Maven右侧依赖Dependencies消失

项目右侧的Maven依赖Dependencies突然消失&#xff0c;项目中的注解都出现报错&#xff0c;出现这种情况应该是因为IDEA版本早于maven版本&#xff0c;重新检查项目中的Maven路径&#xff0c;选择File->Settings->搜索Maven&#xff0c;检查Maven home directory&#xf…

可以写进简历的kafka优化-----吞吐量提升一倍的方法

冲突 在看到项目工程里kafka 生产端配置的batch.size为500&#xff0c;而实际业务数据平均有1K大小的时候&#xff1b;我有点懵了。是的&#xff0c;这里矛盾了&#xff1b;莫非之前的作者认为这个batch.size是发送的条数&#xff0c;而不是kafka生产端内存缓存记录的大小&…