010 Volatile和本地线程

文章目录

  • 关键字Volatile
    • 可见性:
    • 原子性:
    • 有序性:
  • 本地线程
    • 如何创建ThreadLocal变量
    • 如何访问ThreadLocal变量
    • 关于InheritableThreadLocal

关键字Volatile

Volatile是轻量级的synchronized,在多处理器环境下,可以保证共享变量的可见性。它不会引起线程上下文的切换和调度,正确的使用Volatile,比synchronized的使用和执行成本更低。

可见性:

可见性,是指线程之间的可见性,一个线程修改的状态对另一个线程是可见的。也就是一个线程修改一个共享变量时,另一个线程马上就能看到。比如:用volatile修饰的变量,就会具有可见性。
volatile修饰的变量不允许线程内部缓存和重排序,即直接修改内存。所以对其他线程是可见的。但是这里需要注意一个问题,volatile只能让被他修饰内容具有可见性,但不能保证它具有原子性。比如 volatile int a = 0;之后有一个操作 a++;这个变量a具有可见性,但是a++ 依然是一个非原子操作,也就是这个操作同样存在线程安全问题。
  在 Java 中 volatile、synchronized 和 final 实现可见性。

原子性:

原子是世界上的最小单位,具有不可分割性。比如 a=0;(a非long和double类型) 这个操作是不可分割的,那么我们说这个操作时原子操作。再比如:a++; 这个操作实际是a = a + 1;是可分割的,所以他不是一个原子操作。非原子操作都会存在线程安全问题,需要我们使用同步技术
(sychronized)来让它变成一个原子操作。一个操作是原子操作,那么我们称它具有原子性。java的concurrent包下提供了一些原子类,我们可以通过阅读API来了解这些原子类的用法。比如:AtomicInteger、AtomicLong、AtomicReference等。
  在 Java 中 synchronized 和在 lock、unlock 中操作保证原子性。

有序性:

Java 语言提供了 volatile 和 synchronized 两个关键字来保证线程之间操作的有序性,
volatile 是因为其本身包含“禁止指令重排序”的语义,synchronized 是由“一个变量在同一个时刻只允许一条线程对其进行 lock 操作”这条规则获得的,此规则决定了持有同一个对象锁的两个同步块只能串行执行。
 Java语言提供了一种稍弱的同步机制,即volatile变量,用来确保将变量的更新操作通知到其他线程。当把变量声明为volatile类型后,编译器与运行时都会注意到这个变量是共享的,因此不会将该变量上的操作与其他内存操作一起重排序。volatile变量不会被缓存在寄存器或者对其他处理器不可
见的地方,因此在读取volatile类型的变量时总会返回最新写入的值。
  在访问volatile变量时不会执行加锁操作,因此也就不会使执行线程阻塞,因此volatile变量是一种比sychronized关键字更轻量级的同步机制。
当一个变量定义为 volatile 之后,将具备两种特性:

  • 保证此变量对所有的线程的可见性,这里的“可见性”,如本文开头所述,当一个线程修改了这个变量的值,volatile 保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新。但普通变量做不到这点,普通变量的值在线程间传递均需要通过主内存来完成。
  • 禁止指令重排序优化。有volatile修饰的变量,赋值后多执行了一个“load addl $0x0,
    (%esp)”操作,这个操作相当于一个内存屏障(指令重排序时不能把后面的指令重排序到内存屏障之前的位置),只有一个CPU访问内存时,并不需要内存屏障;(什么是指令重排序:是指CPU采用了允许将多条指令不按程序规定的顺序分开发送给各相应电路单元处理。

本地线程

Java中的ThreadLocal类允许我们创建只能被同一个线程读写的变量。因此,如果一段代码含有一个ThreadLocal变量的引用,即使两个线程同时执行这段代码,它们也无法访问到对方的ThreadLocal变量。

如何创建ThreadLocal变量

以下代码展示了如何创建一个ThreadLocal变量:


private ThreadLocal myThreadLocal = new ThreadLocal();

我们可以看到,通过这段代码实例化了一个ThreadLocal对象。我们只需要实例化对象一次,并且也不需要知道它是被哪个线程实例化。虽然所有的线程都能访问到这个ThreadLocal实例,但是每个线程却只能访问到自己通过调用ThreadLocal的set()方法设置的值。即使是两个不同的线程在同一个
ThreadLocal对象上设置了不同的值,他们仍然无法访问到对方的值。

如何访问ThreadLocal变量

一旦创建了一个ThreadLocal变量,你可以通过如下代码设置某个需要保存的值:


myThreadLocal.set("A thread local value”);

可以通过下面方法读取保存在ThreadLocal变量中的值:


String threadLocalValue = (String) myThreadLocal.get();

ThreadLocal例子:


public class ThreadLocalExample {public static class MyRunnable implements Runnable {private ThreadLocal threadLocal = new ThreadLocal();@Overridepublic void run() {threadLocal.set((int) (Math.random() * 100D));try {Thread.sleep(2000);} catch (InterruptedException e) {}System.out.println(threadLocal.get());}}public static void main(String[] args) {MyRunnable sharedRunnableInstance = new MyRunnable();Thread thread1 = new Thread(sharedRunnableInstance);Thread thread2 = new Thread(sharedRunnableInstance);thread1.start();thread2.start();}
}

上面的例子创建了一个MyRunnable实例,并将该实例作为参数传递给两个线程。两个线程分别执行run()方法,并且都在ThreadLocal实例上保存了不同的值。如果它们访问的不是ThreadLocal对象并且调用的set()方法被同步了,则第二个线程会覆盖掉第一个线程设置的值。但是,由于它们访问的是
一个ThreadLocal对象,因此这两个线程都无法看到对方保存的值。也就是说,它们存取的是两个不同的值。

关于InheritableThreadLocal

InheritableThreadLocal类是ThreadLocal类的子类。ThreadLocal中每个线程拥有它自己的值,与ThreadLocal不同的是,InheritableThreadLocal允许一个线程以及该线程创建的所有子线程都可以访问它保存的值。

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

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

相关文章

蝙蝠优化算法(Bat Algorithm,BA)及其Python和MATLAB实现

蝙蝠优化算法(Bat Algorithm,简称BA)是一种基于蝙蝠群体行为的启发式优化算法,由Xin-She Yang于2010年提出。该算法模拟了蝙蝠捕食时在探测目标、适应环境和调整自身位置等过程中的行为,通过改进搜索过程来实现优化问题…

UML2.0-系统架构师(二十四)

1、(重点)系统()在规定时间内和规定条件下能有效实现规定功能的能力。它不仅取决于规定的使用条件等因素,还与设计技术有关。 A可靠性 B可用性 C可测试性 D可理解性 解析: 可靠性:规定时间…

ServiceImpl中的参数封装为Map到Mapper.java中查询

ServiceImpl中的参数封装为Map到Mapper.java中查询,可以直接从map中获取到key对应的value

论文阅读【时间序列】DSformer

论文阅读【时间序列】DSformer arxive: DSformer: A Double Sampling Transformer for Multivariate Time Series Long-term Prediction github: MTST 分类:多变量时间序列(Multivariate time series) 核心观点 多变量时间序列3个维度信息 …

Spring Cloud Alibaba组件概览

目录 Spring Cloud Alibaba组件概览引言一、Spring Cloud Alibaba概述二、Spring Cloud Alibaba组件概览2.1 Nacos2.1.1 概述2.1.2 特点2.1.3 应用场景2.1.4 实例分析 2.2 Sentinel2.2.1 概述2.2.2 特点2.2.3 应用场景2.2.4 实例分析 2.3 RocketMQ2.3.1 概述2.3.2 特点2.3.3 应…

Android AlertDialog对话框

目录 AlertDialog对话框普通对话框单选框多选框自定义框 AlertDialog对话框 部分节选自博主编《Android应用开发项目式教程》(机械工业出版社)2024.6 在Android中,AlertDialog弹出对话框用于显示一些重要信息或者需要用户交互的内容。 弹出…

【Linux进阶】磁盘分区2——MBR和GPT

1.磁盘的分区 因为如果你的磁盘被划分成两个分区,那么每个分区的设备文件名是什么? 在了解这个问题之前,我们先来复习一下磁盘的组成,因为现今磁盘的划分与它物理的组成很有关系。 我们谈过磁盘主要由碟片、机械手臂、磁头与主轴马…

Go 语言 UUID 库 google/uuid 源码解析:时钟信息

google/uuid 库地址 google/uuid 时间相关的部分汇聚在 uuid 包下的 time.go 文件中。 UUID 的 RFC 4122 变体中的版本1和版本2依赖于时钟信息,所以 uuid 库将时钟信息的实现定义在本文件中,供对应版本 UUID 的生成使用。 UUID 依赖于时钟信息的实现版…

5G NR与4G LTE的技术差异

5G NR与4G LTE的技术差异 5G与4G相比,5G(NR)技术有以下优势点: 一、总体技术方面 系统消息 4G(LTE): 支持在任何条件(或情况)下始终开启所有系统消息的广播,导致大量资源浪费,且终端(UE)需要持续评估。 系统信息广播是终端(UE)…

gda动态调试-cnblog

忽的发现gda有动态调试功能 动态监听返回值 框柱指定方法,选择调试方法,gda会自动监听函数的返回值,例如 自定义frida脚本 gda会自动生成hook该函数的frida脚本

window.ai 开启你的内置AI之旅

❝ 成功是得你所想,幸福是享你所得 大家好,我是柒八九。一个专注于前端开发技术/Rust及AI应用知识分享的Coder ❝ 此篇文章所涉及到的技术有 AI( Gemini Nano) Chrome Ollama 因为,行文字数所限,有些概念可能会一带而过亦或者提供…

【matlab】回归预测/异常检测——智能优化算法极限学习机

目录 引言 基本原理 主要特点 应用领域 发展趋势 智能优化算法——蜣螂优化算法(DBO) 算法原理 算法特点 应用前景 代码实现 ELM训练函数——elmtrain 函数 ELM预测函数——elmpredict 函数 适应度函数 主函数 引言 极限学习机(…

【C++设计模式】(二)设计模式简介

(二)设计模式简介 设计模式的概念来源于建筑学,最早由建筑学家克里斯托弗亚历山大(Christopher Alexander)在其著作《建筑的模式语言》(A Pattern Language)中提出。亚历山大提出了一系列在建筑…

【数据挖掘】银行信用卡风险大数据分析与挖掘

银行信用卡风险大数据分析与挖掘 1、实验目的 中国某个商业银行高层发现自家信用卡存在严重的欺诈和拖欠现象,已经影响到自身经营和发展。银行高层希望大数据分析部门采用数据挖掘技术,对影响用户信用等级的主要因素进行分析,结合信用卡用户的人口特征属性对欺诈行为和拖欠…

顶顶通呼叫中心中间件-外呼通道变量同步到坐席通道变量(mod_cti基于Freeswitch)

机器人伴随转人工或者排队转人工 把外呼通道同步到坐席通道变量 在拨号方案转人工动作cti_acd,或者转机器人动作cti_rotobt的前面,添加一个 export nolocal:变量名${变量名} 一、配置拨号方案 win-ccadmin配置方法 点击拨号方案 -> 点击进入排队 -> 根据图…

Java项目:基于SSM框架实现的中小企业人力资源管理系统【ssm+B/S架构+源码+数据库+开题报告+毕业论文】

一、项目简介 本项目是一套基于SSM框架实现的中小企业人力资源管理系统 包含:项目源码、数据库脚本等,该项目附带全部源码可作为毕设使用。 项目都经过严格调试,eclipse或者idea 确保可以运行! 该系统功能完善、界面美观、操作简…

智能生产管理系统设计

智能生产管理系统的设计旨在提升制造业的效率、灵活性和响应速度,通过集成先进的信息技术(如物联网IoT、大数据分析、人工智能AI、云计算等)实现生产过程的智能化。以下是一些关键设计要素和步骤,用于构建一个高效的智能生产管理系…

jmeter-beanshell学习2-beanshell断言

继续写,之前写了获取变量,设置变量,今天先写个简单点的断言。 一般情况用响应断言,就挺好使,但是自动化还要生成报告,如果断言失败了,要保存结果,只能用beanshell处理,顺…

Ubuntu 24.04-自动安装-Nvidia驱动

教程 但在安全启动模式下可能会报错。 先在Nvidia官网找到GPU对应的驱动版, 1. 在软件与更新中选择合适的驱动 2. ubuntu自动安装驱动 sudo ubuntu-drivers autoinstall显示驱动 ubuntu-drivers devices3. 安装你想要的驱动 sudo apt install nvidia-driver-ve…

如何在 SwiftUI 中熟练使用 sensoryFeedback 修饰符

文章目录 前言背景介绍平台支持仅支持watchOS支持watchOS和iOS 基本用法预定义样式根据触发器值选择样式使用场景当值更改时触发使用条件闭包触发使用反馈闭包触发 可以运行 Demo总结 前言 SwiftUI 引入了新的 sensoryFeedback 视图修饰符,使我们能够在所有 Apple …