深刻解析 volatile 关键字和线程本地存储ThreadLocal
1.volatile关键字在Java多线程编程中的重要性
在多线程编程中,volatile关键字扮演着至关重要的角色,它确保了变量在多个线程间的可见性,并且能防止指令重排序,从而达到线程安全的目的。
1.1 保证多线程环境下变量的可见性
在Java的并发编程中,线程间共享变量的更新可能不会立即对其他线程可见,这是因为线程可以把变量保留在局部内存中。而使用volatile声明的变量可以强制线程读写直接操作主内存,确保每个线程看到的变量是最新的值。
class SharedObject {volatile int sharedCounter;void increment() {sharedCounter++;}
}
1.2 禁止指令重排序
处理器为了提高程序运行效率,可能会对指令序进行优化,使得实际执行的顺序与代码编写的顺序不一致。对于单线程程序这通常不是问题,但在多线程中可能导致严重错误。volatile关键字可以禁止这种重排序,确保程序的执行顺序与代码的顺序一致。
1.3 volatile vs synchronized:使用场景与性能比较
volatile和synchronized都可以解决多线程中的数据同步问题,但volatile由于不会引起线程上下文的切换或调度,因此开销比synchronized小,适用于轻量级的同步需求,如状态标记。
class VolatileExample {volatile boolean isRunning = true;void run() {while (isRunning) {// ...}}
}
1.4 实例:使用volatile保证操作的原子性
虽然volatile可以保证变量的可见性,但它并不能保证复合操作(如i++)的原子性。在使用volatile时仍需注意,对于复合操作需要额外的同步策略。
2.在Java中实现线程间的数据共享
数据共享是多线程编程的核心问题之一,正确地在多个线程间共享数据是实现并发程序的关键步骤。
2.1 设计线程安全的共享数据类
线程安全的数据类通常包含了同步机制,以确保在任意时刻只有一个线程能够写入共享数据,同时可以由多个线程读取数据而不会发生冲突。
public class SafeSharedData {private int data;// 同步方法,保持方法原子性public synchronized void setData(int value) {this.data = value;}public synchronized int getData() {return data;}
}
2.2 通过内部类实现Runnable接口
您可以通过内部类来包装共享数据和它的操作,然后实现Runnable接口,使得线程能够操作同一个数据实例。
public class SharedDataWrapper implements Runnable {private SafeSharedData sharedData;public SharedDataWrapper(SafeSharedData data) {this.sharedData = data;}@Overridepublic void run() {// 使用sharedData的同步方法操作数据}
}
2.3 使用锁机制同步数据访问
ReentrantLock是一种广泛使用的锁机制,能够对数据访问进行精准的控制。这个锁支持锁重入,意味着可以在一个锁已经被获取的前提下,再次获取此锁不会产生死锁。
import java.util.concurrent.locks.ReentrantLock;
public class Counter {private final ReentrantLock lock = new ReentrantLock();private int count = 0;public void increment() {lock.lock(); // 获取锁try {count++;} finally {lock.unlock(); // 释放锁}}public int getCount() {lock.lock(); // 获取锁try {return count;} finally {lock.unlock(); // 释放锁}}
}
使用锁时,一定要在try-finally块中释放所持有的锁,以避免死锁或资源泄漏。
3.ThreadLocal的使用及其对多线程的影响
ThreadLocal是Java提供的一种线程局部存储机制,允许每个线程在其内部保存数据,而这些数据对其他线程是隔离的。
3.1 ThreadLocal简介及其工作原理
ThreadLocal通过提供线程内部的私有变量副本,来避免其它线程的干扰和冲突。
public class ThreadLocalExample {private ThreadLocal<Integer> threadLocalCount = new ThreadLocal<>();public void setThreadLocalCount(int value) {threadLocalCount.set(value);}public int getThreadLocalCount() {return threadLocalCount.get();}
}
3.1.1 ThreadLocal类与ThreadLocalMap关系
每个线程内部都有一个ThreadLocalMap,其键值对的键是ThreadLocal对象,而值则是线程内部想要存储的对象。
3.1.2 ThreadLocal与线程隔离性
ThreadLocal确保每一个线程都有一个独立的变量副本,它提供了一种将状态和数据从其它线程隔离开来的手段。
3.2 ThreadLocal在实际编程中的应用场景
ThreadLocal在很多编程场景中非常有用,尤其是与会话信息和用户身份认证有关的场景。
3.2.1 用户身份验证
在Web开发中,可以利用ThreadLocal存储用户登录信息,确保每个线程独立处理各自的用户数据。
3.2.2 数据库连接管理
ThreadLocal可以用于保持数据库连接,使得每个线程都拥有自己的数据库连接,从而提高数据库操作的效率。
3.2.3 会话信息控制
在HTTP服务中,ThreadLocal常用于存储会话信息,满足服务端处理需求。
3.3 实例:ThreadLocal在Web应用中的典型用法
以下是一个在Web应用中使用ThreadLocal来存储当前HTTP请求信息的例子。
public class WebUserContext {private static ThreadLocal<HttpServletRequest> userThreadLocal = new ThreadLocal<>();public static HttpServletRequest getRequest() {return userThreadLocal.get();}public static void setRequest(HttpServletRequest request) {userThreadLocal.set(request);}
}
在这个例子中,我们确保了每个线程只处理它自己的请求,通过存储在ThreadLocal变量中,可以在代码的任何部分方便地获取当前的HttpServletRequest对象,而不用担心其他线程的交叉访问问题。
在这样的用例中,可以在Web请求的初始处理阶段设置ThreadLocal,之后在整个请求处理过程中的任何地方获取这个信息。处理完请求后,很重要的一点是要清理掉ThreadLocal存储的数据,避免内存泄漏。
例如,在一个Servlet过滤器中设定和清除ThreadLocal:
public class UserContextFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {try {WebUserContext.setRequest((HttpServletRequest) request);chain.doFilter(request, response);} finally {WebUserContext.setRequest(null); // 清理ThreadLocal中的数据}}
}
这样的做法可以在每个请求结束时自动清除ThreadLocal中的数据,这是一个良好的实践,帮助避免内存泄漏。
结合前面的章节内容,我们有了对Java多线程中变量使用机制更深入的理解,包括volatile确保变量的可见性和禁止指令重排序,以及如何安全高效地在多线程中共享数据。还有ThreadLocal的使用,它提供了一种保持线程内数据隔离的高效方法,在多线程编程中非常有用,特别是在处理一些线程安全的临时状况或为每个线程维护一个私有的状态。
相关文章:
深刻解析 volatile 关键字和线程本地存储ThreadLocal
1.volatile关键字在Java多线程编程中的重要性 在多线程编程中,volatile关键字扮演着至关重要的角色,它确保了变量在多个线程间的可见性,并且能防止指令重排序,从而达到线程安全的目的。 1.1 保证多线程环境下变量的可见性 在Ja…...
羧甲基纤维素钠(CMC-Na)市场规模不断增长 我国生产企业众多
羧甲基纤维素钠(CMC-Na)市场规模不断增长 我国生产企业众多 羧甲基纤维素钠(CMC-Na)又称CMC-钠,化学式为[C6H7O2(OH)2OCH2COONa]n,是一种离子型纤维素醚。CMC-Na外观呈白色颗粒状或纤…...
网红郭有才是怎么火起来的
网红郭有才的爆火主要归因于以下几个因素: 独特的个人魅力与风格:郭有才以其地道的乡土气息和个人的朴实无华赢得了观众的喜爱。他的视频内容展现了真实且接地气的生活场景,给人以亲切感。同时,他的幽默感也是吸引观众的一个重要因…...
小米8SE刷root(面具)
首先准备好一根数据线,一部小米8SE手机,和一台电脑 接下来需要的软件我会给出链接和使用方法,以及分享我遇到的困难和解决方案 下面操作不会的,可以参考这个博主的教程,我也是跟着这个教程刷好的 第一步解锁BL 开启开…...
如果创办Google
本文是一篇演讲稿,来自于《黑客与画家》一书的作者保罗*格雷厄姆,被称为硅谷创业之父。这是他为14至15岁的孩子们做的一次演讲,内容是关于如果他们将来想创立一家创业公司,现在应该做些什么。很多学校认为应该向学生们传授一些有关…...
邦芒职场:揭秘影响你职场收入的九大细节
在职场这个大舞台上,微小的细节往往能决定你收入的多少。以下九大细节,是你职场成功的关键,不容忽视。 1. 形象塑造 在这个注重第一印象的时代,良好的形象是你的第一张名片。精致的妆容、得体的着装,不仅能为你加分&a…...
Petalinux 制作ZYNQ镜像文件流程
1概述 在Zynq-7000 SoC中搭建运行Linux,嵌入式软件栈。 处理器系统引导是一个分两个阶段的过程。第一个阶段是一个内部 BootROM,它存储 stage-0 的引导代码。BootROM 在 CPU 0 上执行,CPU 1 执行等待事件(WFE)指令。…...
99%的人都不知道,微信才是真正的学习神器
微信,作为一款全球最受欢迎的社交应用之一,除了聊天、朋友圈、小程序等功能外,还有许多隐藏的学习功能,今天小编就给大家分享10个微信隐藏的学习功能,助您轻松成为学霸。 1、微信笔记 用过代办清单软件的朋友都知道&…...
加速模型训练 GPU cudnn
GPU的使用 在定义模型时,如果没有特定的GPU设置,会使用 torch.nn.DataParallel 将模型并行化,充分利用多GPU的性能,这在加速训练上有显著影响。 model torch.nn.DataParallel(model).cuda() cudnn 的配置: cudnn.…...
《python编程从入门到实践》day40
# 昨日知识点回顾 编辑条目及创建用户账户 暂没能解决bug: The view learning_logs.views.edit_entry didnt return an HttpResponse object. It returned None instead.# 今日知识点学习 19.2.5 注销 提供让用户注销的途径 1.在base.html中添加注销链接 …...
IO多路复用学习笔记
参考资料: 视频1 视频2(本人B站也有发布) 视频3 参考笔记 参考博客...
Ubuntu设置中文输入法教程
在Ubuntu中设置中文输入法非常简单,只需按照以下步骤操作即可。 打开“设置”菜单。在Ubuntu的左上角点击“活动”按钮,然后在弹出的菜单中选择“设置”图标。 进入“区域和语言”设置。在设置菜单中,找到并点击“区域和语言”选项。 添加中…...
机器学习之爬山算法(Hill Climbing Algorithm)
爬山算法(Hill Climbing Algorithm)是一种简单而常见的启发式搜索算法,通常用于解决优化问题。它的基本思想类似于登山过程中爬升到山顶的过程,即从一个起始点开始,不断尝试向邻近的点移动,直到找到一个局部最优解。 下面是爬山算法的基本工作流程: 初始化:选择一个初…...
LeetCode - 贪心算法 (Greedy Algorithm) 集合 [分配问题、区间问题]
欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/139242199 贪心算法,是在每一步选择中,都采取当前状态下,最好或最优(即最有利)的选择&…...
Linux中ftp配置
一、ftp协议 1、端口 ftp默认使用20、21端口 20端口用于建立数据连接 21端口用于建立控制连接 2、ftp数据连接模式 主动模式:服务器主动发起数据连接 被动模式:服务器被动等待数据连接 二、ftp安装 yum install -y vsftpd #---下…...
BWVS 靶场测试
一、PHP弱类型 is_numeric() 输入:127.0.0.1/BWVS/bug/php/code.php # 1、源代码分析 如果num不是数字,那么就输出num,同时如果num1,就输出flag。即num要是字符串又要是数字 # 2、函数分析: is_numeric()函数&…...
c++ 里重解释转换之于引用 reinterpret_cast< long >
今天遇到了这一很新奇的写法。模糊中记得王老师也这么讲过。c 里四大转换。把数据重解释为原来数据的引用。虽然也可以直接定义对变量的引用。测试如下: 咱们从反汇编再了解下 c 编译器是怎么处理这种写法的: 谢谢...
JAVASE2
封装的步骤: 1、所有属性私有化,使用private关键字进行修饰,private表示私有的,修饰的所有数据只能在本类中访问 2、对外提供简单入口:比如说被private修饰的成员变量,在其他类中只能通过getXxx/setXxx方法…...
ora-00392 ora-00312错误处理
检查当前日志组状态 对日志组进行clear操作 重新开库无报错...
网页、h5默认滚动条样式重构
文章目录 前言一、使用步骤1、在想要滚动的元素上设置相应的css类名2.设置样式 总结 前言 此文章用于,让我自己快速设置 浏览器、h5 默认滚动条样式…… 一、使用步骤 1、在想要滚动的元素上设置相应的css类名 代码如下: <div class"list scro…...
GHelper硬件控制工具:华硕笔记本性能优化与系统管理完全指南
GHelper硬件控制工具:华硕笔记本性能优化与系统管理完全指南 【免费下载链接】g-helper Lightweight, open-source control tool for ASUS laptops and ROG Ally. Manage performance modes, fans, GPU, battery, and RGB lighting across Zephyrus, Flow, TUF, Str…...
weibo-rss:让微博内容主动找到你的高效订阅工具
weibo-rss:让微博内容主动找到你的高效订阅工具 【免费下载链接】weibo-rss 🍰 把喜欢的微博转为 RSS 订阅源 项目地址: https://gitcode.com/gh_mirrors/we/weibo-rss 在信息爆炸的时代,我们每天要处理大量碎片化内容。微博作为主流社…...
【独家首发】CPython内存管理策略白皮书(基于v3.9–v3.13源码比对):37处关键宏定义、12个GC阈值参数、8类对象内存布局差异
第一章:CPython内存管理策略全景概览CPython 作为 Python 官方解释器,其内存管理机制融合了引用计数、循环垃圾回收(GC)与分代回收策略,形成一套兼顾实时性与鲁棒性的综合体系。理解该机制对诊断内存泄漏、优化对象生命…...
Windows 11上保姆级教程:用Ollama本地部署DeepSeek-R1 8B,再也不用担心API费用和网络延迟了
Windows 11本地AI部署实战:OllamaDeepSeek-R1 8B全流程指南 在AI技术快速发展的今天,越来越多的开发者和中小企业开始关注如何在本地环境中部署和运行大型语言模型。对于预算有限但对数据隐私有高要求的团队来说,本地部署不仅能显著降低成本&…...
二极管限幅与钳位电路设计全解析
1. 二极管基础特性回顾 在开始分析各种二极管应用电路之前,我们先快速回顾一下二极管的核心特性。二极管最显著的特点就是其单向导电性 - 当正向偏置电压超过导通阈值(硅管约0.7V)时导通,反向偏置或正向电压不足时截止。这个看似简…...
10分钟零成本搭建KIMI AI免费API:个人智能助手完整指南
10分钟零成本搭建KIMI AI免费API:个人智能助手完整指南 【免费下载链接】kimi-free-api 🚀 KIMI AI 长文本大模型逆向API【特长:长文本解读整理】,支持高速流式输出、智能体对话、联网搜索、探索版、K1思考模型、长文档解读、图像…...
AI爆款!官方定名!“Token”变身“词元”,10个token=10个AI点数?这才是它真正的含义!
Token 最近,一个原本只在技术圈流传的词,突然迎来正式“官宣”—— Token的中文名被官方确定为:词元。 这个你可能天天听、却从没认真探究过的词,正在变成大众的“通用语言”。 但很多人不知道,Token并不是AI时代的新词…...
如何高效使用Dism++:Windows系统维护的终极解决方案
如何高效使用Dism:Windows系统维护的终极解决方案 【免费下载链接】Dism-Multi-language Dism Multi-language Support & BUG Report 项目地址: https://gitcode.com/gh_mirrors/di/Dism-Multi-language 你是否曾为Windows系统运行缓慢而烦恼?…...
BCompare_Keygen 授权激活实战指南:从评估错误到专业版授权的全面解决方案
BCompare_Keygen 授权激活实战指南:从评估错误到专业版授权的全面解决方案 【免费下载链接】BCompare_Keygen Keygen for BCompare 5 项目地址: https://gitcode.com/gh_mirrors/bc/BCompare_Keygen 【问题定义】Beyond Compare 评估期结束的核心痛点 当Bey…...
Enhancing Large Language Model Reasoning with Knowledge Graph Paths: A Faithful and Interpretable Ap
1. 为什么大模型需要知识图谱的"导航系统"? 想象一下,你被突然扔进一个陌生城市,手上只有一本过期的旅游指南。这时候如果有个本地人拿着最新地图给你指路,是不是完全不一样?这就是当前大语言模型࿰…...
