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

Volatile的内存语义

1、volatile的特性

可见性:对一个volatile变量的读,总能够看到任意一个线程对这个volatile变量的写入。

原子性:对任意单个volatile变量的读/写具有原子性,但类似于volatile++这种复合操作不具有原子性。

接下来我们用程序验证。


public class OldVolatileFeaturesExample {volatile long v1 = 0L;      // 使用volatile 声明64位的long型变量//long v1 = 0L;public void set(long l){v1 = l;                 //单个volatile 变量的写}public void getAndIncrement(){v1++;                   // 多个volatile 变量的读/写}public long get(){return v1;              //  单个volatile 变量的读}public static void main(String[] args) {final OldVolatileFeaturesExample volatileFeaturesExamlple = new OldVolatileFeaturesExample();Thread thread0 = new Thread(new Runnable() {public void run() {volatileFeaturesExamlple.set(1L);}});thread0.start();Thread thread1 = new Thread(new Runnable() {public void run() {volatileFeaturesExamlple.getAndIncrement();}});thread1.start();Thread thread2 = new Thread(new Runnable() {public void run() {long l = volatileFeaturesExamlple.get();System.out.println("创建的l值-------"+ l);}});thread2.start();/*        for (int i = 0; i < 10; i++) {Thread thread0 = new Thread(new Runnable() {public void run() {volatileFeaturesExamlple.set(1L);}});thread0.start();Thread thread1 = new Thread(new Runnable() {public void run() {volatileFeaturesExamlple.getAndIncrement();}});thread1.start();Thread thread2 = new Thread(new Runnable() {public void run() {long l = volatileFeaturesExamlple.get();System.out.println("创建的l值-------"+ l);}});thread2.start();}*/}}

这里,线程thread0 设置使用volatile修饰的long类型变量 v1 ;线程thread1 进行v1++操作, thread2 获取变量v1的值,并打印结果。那么 v1的值是几呢?

上面这段程序运行结果是:

创建的l值-------2

那么就算不用volatile修饰的v1变量,也执行上述操作,结果会是什么样子呢?没错,还是2。

那么使用volatile修饰的v1变量 当使用for 循环呢?也就是多个volatile变量的读写操作的结果:


创建的l值-------2
创建的l值-------2
创建的l值-------1
创建的l值-------1
创建的l值-------1
创建的l值-------2
创建的l值-------3
创建的l值-------1
创建的l值-------2
创建的l值-------3

假设具有原子性,那么v1循环加10次 1,那么它的结果应该是 10,而不是上面的结果。上面的程序等价于:

public class NewVolatileFeaturesExample {long v1 = 0L;public synchronized void set(long l){  //对单个的普通变量的写用同一个锁同步v1 = l;}public void getAndIncrement(){         //普通方法调用long temp = get();                 //调用已同步的读方法temp += 1L;                        //普通写操作set(temp);                         //调用已同步的写方法}public synchronized long get(){         // 对单个的普通变量的读用同一个锁同步return v1;}public static void main(String[] args) {final NewVolatileFeaturesExample newVolatileFeaturesExample = new NewVolatileFeaturesExample();/*        for (int i = 0; i < 10; i++) {Thread thread0 = new Thread(new Runnable() {public void run() {newVolatileFeaturesExample.set(1L);}});thread0.start();Thread thread1 = new Thread(new Runnable() {public void run() {newVolatileFeaturesExample.getAndIncrement();}});thread1.start();Thread thread2 = new Thread(new Runnable() {public void run() {long l = newVolatileFeaturesExample.get();System.out.println("创建的l值-------"+ l);}});thread2.start();}*/Thread thread0 = new Thread(new Runnable() {public void run() {newVolatileFeaturesExample.set(1L);}});thread0.start();Thread thread1 = new Thread(new Runnable() {public void run() {newVolatileFeaturesExample.getAndIncrement();}});thread1.start();Thread thread2 = new Thread(new Runnable() {public void run() {long l = newVolatileFeaturesExample.get();System.out.println("创建的l值-------"+ l);}});thread2.start();}
}

这个也就是相当于对v1变量的读和写进行了synchronized 同步锁操作。

而锁的语义决定了临界区代码的执行具有原子性。锁的happens-before 规则保证了释放锁和获取锁的两个线程之间的内存可见性。那么volatile 写和读建立的happens-before 关系是又是什么样子呢?欲知后事如何,请看下回分解。

更多创作在我的公众号里哦。
在这里插入图片描述

相关文章:

Volatile的内存语义

1、volatile的特性 可见性&#xff1a;对一个volatile变量的读&#xff0c;总能够看到任意一个线程对这个volatile变量的写入。 原子性&#xff1a;对任意单个volatile变量的读/写具有原子性&#xff0c;但类似于volatile这种复合操作不具有原子性。 接下来我们用程序验证。…...

Debezium+Kafka:Oracle 11g 数据实时同步至 DolphinDB 解决方案

随着越来越多用户使用 DolphinDB&#xff0c;各式各样的应用场景对 DolphinDB 的数据接入提出了不同的要求。部分用户需要将 Oracle 11g 的数据实时同步到 DolphinDB 中来&#xff0c;以满足在 DolphinDB 中实时使用数据的需求。本篇教程将介绍使用 Debezium 来实时捕获和发布 …...

前端如何在 WebSocket 的请求头中使用标准 HTTP 头携带 Authorization 信息,添加请求头

WebSocket 的请求头(header)中如何携带 authorization...

Java---图书管理系统(练习版)

1.主函数 import book.Book; import book.BookList; import user.AdminUser; import user.NormalUser; import user.User;import java.util.Scanner;public class Main {public static User Login(){//确认你的身份System.out.println("请输如你的名字");Scanner sc…...

ICML2024 定义新隐私保护升级:DP-BITFIT新型微调技术让AI模型学习更安全

DeepVisionary 每日深度学习前沿科技推送&顶会论文分享&#xff0c;与你一起了解前沿深度学习信息&#xff01; 引言&#xff1a;差分隐私在大模型微调中的重要性和挑战 在当今的深度学习领域&#xff0c;大型预训练模型的微调已成为提高各种任务性能的关键技术。然而&am…...

网络空间安全数学基础·整除与同余

主要内容&#xff1a; 整除的基本概念&#xff08;掌握&#xff09; 素数&#xff08;掌握&#xff09; 同余的概念&#xff08;掌握&#xff09; 1.1整除 定义&#xff1a;设a&#xff0c;b是任意两个整数&#xff0c;其中b≠0&#xff0c;如果存在一个整数q&#xff0c;使 …...

同旺科技 FLUKE ADPT 隔离版发布 ---- 说明书

所需设备&#xff1a; 1、FLUKE ADPT 隔离版 内附链接&#xff1b; 应用于&#xff1a;福禄克Fluke 12E / 15BMax / 17B Max / 101 / 106 / 107 应用于&#xff1a;福禄克Fluke 15B / 17B / 18B...

云计算-角色、特性和模型 (Roles, Characteristics, and Models)

角色、特性和模型 (Roles, Characteristics, and Models) 角色和边界 (Roles and Boundaries) 为了识别云计算模型&#xff0c;我们首先需要了解各种参与者的角色和边界。由于云系统通常遵循面向服务的模型&#xff0c;我们需要了解服务提供者和服务订阅者之间的边界。我们将遵…...

介绍一下Hugging Face,这个公司的背景是什么

Hugging Face是一家成立于2016年的人工智能公司&#xff0c;专注于为AI研究人员和开发者提供开源模型库和工具。以下是关于Hugging Face公司的详细背景介绍&#xff1a; 公司历史与创始人&#xff1a; Hugging Face由Clment Delangue、Julien Chaumond和Thomas Wolf三位法国籍…...

【C++高阶(一)】继承

目录 一、继承的概念 1.继承的基本概念 2.继承的定义和语法 3.继承基类成员访问方式的变化 ​编辑 4.总结 二、基类和派生类对象赋值转换 三、继承中的作用域 四、派生类的默认成员函数 1.派生类中的默认构造函数 2.派生类中的拷贝构造函数 3.派生类中的移动构造函数…...

AI原生嵌入式矢量模型数据库ChromaDB-部署与使用指南

在人工智能大模型领域&#xff0c; 离不开NLP技术&#xff0c;在NLP中词向量是一种基本元素&#xff0c;如何存储这些元素呢&#xff1f; 可以使用向量数据库ChromeDB Chroma Chroma 是 AI 原生开源矢量数据库。Chroma 通过为 LLM 提供知识、事实和技能&#xff0c;使构建 L…...

c# 画一个正弦函数

1.概要 c# 画一个正弦函数 2.代码 using System; using System.Drawing; using System.Windows.Forms;public class SineWaveForm : Form {private const int Width 800;private const int Height 600;private const double Amplitude 100.0;private const double Period…...

Docker学习(3):镜像使用

当运行容器时&#xff0c;使用的镜像如果在本地中不存在&#xff0c;docker 就会自动从 docker 镜像仓库中下载&#xff0c;默认是从 Docker Hub 公共镜像源下载。 一、列出镜像列表 可以使用 docker images 来列出本地主机上的镜像。 各个选项说明&#xff1a; REPOSITORY&am…...

【Git】版本控制工具——Git介绍及使用

目录 版本控制版本控制系统的主要目标分类小结 分布式版本控制系统——GitGit特点Git与SVN的区别Git的工作机制 Git安装Git 团队协作机制团队内协作跨团队协作远程仓库远程仓库的作用有以下几个方面远程仓库操作流程/团队协作流程 Git分支什么是分支分支的好处 Git的常用命令Gi…...

面试八股之JVM篇3.6——垃圾回收——强引用、弱引用、虚引用、软引用

&#x1f308;hello&#xff0c;你好鸭&#xff0c;我是Ethan&#xff0c;一名不断学习的码农&#xff0c;很高兴你能来阅读。 ✔️目前博客主要更新Java系列、项目案例、计算机必学四件套等。 &#x1f3c3;人生之义&#xff0c;在于追求&#xff0c;不在成败&#xff0c;勤通…...

博客摘录「 Sql Server 收缩日志文件原理及always on 下的实践」2024年5月22日

四、Always on 环境下实践   先对数据库进行完整备份&#xff1a; EXEC sp_configure show advanced options, 1; RECONFIGURE; EXEC sp_configure xp_cmdshell, 1; RECONFIGURE; DECLARE DbName NVARCHAR(1000); DECLARE myCursor CURSOR LOCAL STATIC FOR S…...

每日一题(5)——StringBuffer操作

编写程序&#xff0c;对StringBuffer对象进行追加&#xff0c;插入和修改缓冲区长度等操作&#xff1b; class StringDemo{public static void main(String[] args){boolean btrue;int i321;long l123456;String s1new String("Hello,world!");StringBuffer s2new S…...

默认路由实现两个网段互通实验

默认路由实现两个网段互通实验 **默认路由&#xff1a;**是一种特殊的静态路由&#xff0c;当路由表中与数据包目的地址没有匹配的表项时&#xff0c;数据包将根据默认路由条目进行转发。默认路由在某些时候是非常有效的&#xff0c;例如在末梢网络中&#xff0c;默认路由可以…...

ComfyUI完全入门:图生图局部重绘

大家好&#xff0c;我是每天分享AI应用的萤火君&#xff01; 这篇文章的主题和美女有关&#xff0c;不过并不是教大家生产美女视频&#xff0c;而是讲解 ComfyUI 的图生图局部重绘&#xff0c;其中将会以美女图片为例&#xff0c;来展示局部重绘的强大威力。 先看看效果&…...

基于UDP的网络多人聊天室

UDP服务器 #include <myheader.h>//宏定义打印错误信息 #define PRINT_ERR(msg) \do \{ \printf("%S,%D,%S\n",__FI…...

【JavaEE】-- HTTP

1. HTTP是什么&#xff1f; HTTP&#xff08;全称为"超文本传输协议"&#xff09;是一种应用非常广泛的应用层协议&#xff0c;HTTP是基于TCP协议的一种应用层协议。 应用层协议&#xff1a;是计算机网络协议栈中最高层的协议&#xff0c;它定义了运行在不同主机上…...

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接&#xff0c;私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

8k长序列建模,蛋白质语言模型Prot42仅利用目标蛋白序列即可生成高亲和力结合剂

蛋白质结合剂&#xff08;如抗体、抑制肽&#xff09;在疾病诊断、成像分析及靶向药物递送等关键场景中发挥着不可替代的作用。传统上&#xff0c;高特异性蛋白质结合剂的开发高度依赖噬菌体展示、定向进化等实验技术&#xff0c;但这类方法普遍面临资源消耗巨大、研发周期冗长…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务

通过akshare库&#xff0c;获取股票数据&#xff0c;并生成TabPFN这个模型 可以识别、处理的格式&#xff0c;写一个完整的预处理示例&#xff0c;并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务&#xff0c;进行预测并输…...

数据库分批入库

今天在工作中&#xff0c;遇到一个问题&#xff0c;就是分批查询的时候&#xff0c;由于批次过大导致出现了一些问题&#xff0c;一下是问题描述和解决方案&#xff1a; 示例&#xff1a; // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...

分布式增量爬虫实现方案

之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面&#xff0c;避免重复抓取&#xff0c;以节省资源和时间。 在分布式环境下&#xff0c;增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路&#xff1a;将增量判…...

【Go语言基础【13】】函数、闭包、方法

文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数&#xff08;函数作为参数、返回值&#xff09; 三、匿名函数与闭包1. 匿名函数&#xff08;Lambda函…...