深刻解析 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…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...
HBuilderX安装(uni-app和小程序开发)
下载HBuilderX 访问官方网站:https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本: Windows版(推荐下载标准版) Windows系统安装步骤 运行安装程序: 双击下载的.exe安装文件 如果出现安全提示&…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
数据结构:递归的种类(Types of Recursion)
目录 尾递归(Tail Recursion) 什么是 Loop(循环)? 复杂度分析 头递归(Head Recursion) 树形递归(Tree Recursion) 线性递归(Linear Recursion)…...
一些实用的chrome扩展0x01
简介 浏览器扩展程序有助于自动化任务、查找隐藏的漏洞、隐藏自身痕迹。以下列出了一些必备扩展程序,无论是测试应用程序、搜寻漏洞还是收集情报,它们都能提升工作流程。 FoxyProxy 代理管理工具,此扩展简化了使用代理(如 Burp…...
