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

良好的并发编程习惯之封闭(Confinement)

创作内容丰富的干货文章很费心力,感谢点过此文章的读者,点一个关注鼓励一下作者,激励他分享更多的精彩好文,谢谢大家!


“共享可变状态”有两个要点:“共享”和“可变”。封闭的策略是:不共享就完事了。

《Java 并发编程实战》一书中列举了三种封闭的方式。

  • Ad-hoc 线程封闭
  • 栈封闭
  • ThreadLocal 类

Ad-hoc 封闭

"Ad-hoc" 一般指“特别的、专门的、临时的”等,在编程的语境中一般指“具体情况具体分析”。Ad-hoc 封闭也就指由程序自己实现的封闭。

例如有个 volatile 变量,在编写代码的时候,隐含实现了这样的约定:只有一个线程会“写”该变量,其它线程只会“读”操作。那么这种情况下这个“写线程”即使做了 "Check-then-Act" 操作也是线程安全的。

所以 Ad-hoc 封闭也只能是“具体情况具体分析”了。

栈封闭

局部变量(local variables)在方法调用时被分配到栈上,正常情况下当方法返回时就被销毁(不再被引用,可以被 GC 回收),只存在于调用的线程中。这些变量由于不会被共享,即使变量本身并不是线程安全的,也不用担心方法的线程安全性。

当然如果局部变量通过一些方式在方法调用结束后依旧被引用,则不再是“封闭”的,就会有线程安全的问题。如变量被作为方法的返回值被返回;被方法里创建的线程引用;引用被保存到了其它地方,如实例变量(instance variable)等。

一般如果一个方法只依赖它的输入参数和方法内创建的局部变量,不依赖其它的全局的信息,则可以说这个方法是“无状态”的。

ThreadLocal 类

ThreadLocal 也可以认为是前文所说的“线程安全类”,只不过 ThreadLocal 的语义上就是“线程封闭”的。

ThreadLocal 的作用是为每个线程保存一个副本,每个线程在调用 get 或 set 方法时都只会操作本线程的副本。由于每个线程只用自己的那份,不存在共享行为,因此是线程安全的。

一般来说,如果有一些对象从作用是可以做成单例,但它本身又不是线程安全的,就可以使用 ThreadLocal 为每个线程创建一个副本,就可以线程安全地把它作为单例使用了。

例如,我们知道 SimpleDateFormat 不是线程安全的,但是通过 ThreadLocal 的包装,就可以做到线程封闭,不在线程间共享,做到线程安全,如下示例:

public class DateUtil {private static ThreadLocal<SimpleDateFormat> dateFormat = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));public static String formatDate(Date date) throws ParseException {return dateFormat.get().format(date);}
}

要注意的是,由于需要为每个线程创建一个副本,如果初始化的代价比较高且经常性地创建新的线程,可能会有潜在的性能问题,虽然通常情况下不会成为问题。

另外,不要把从 ThreadLocal 获取的引用保存到其它地方,会有潜在的线程安全问题。

小结

封闭策略用人话来说就是:尽量不要用全局变量,如果全局变量是单例,考虑用 ThreadLocal 包装。

相关文章:

良好的并发编程习惯之封闭(Confinement)

创作内容丰富的干货文章很费心力&#xff0c;感谢点过此文章的读者&#xff0c;点一个关注鼓励一下作者&#xff0c;激励他分享更多的精彩好文&#xff0c;谢谢大家&#xff01; “共享可变状态”有两个要点&#xff1a;“共享”和“可变”。封闭的策略是&#xff1a;不共享就完…...

docker镜像、容器、仓库介绍

docker docker介绍docker镜像命令docker容器命令docker仓库 docker介绍 官网 Docker 是一种开源的容器化平台&#xff0c;用于开发、部署和运行应用。它通过将应用程序及其依赖项打包到称为“容器”的单一包中&#xff0c;使得应用能够在任何环境下运行&#xff0c;不受底层系…...

写个添加球队和展示球队的功能--laravel与inertia

先展示下最终效果,如下是展示球队的界面 如下是添加球队的界面 界面样式没怎么调整,不要在意这些细节。先说说操作流程 首先需要登录,没注册就注册一个账号。登录界面就不展示了。然后选中”NbaBasketballTeams“这个选项,就进入了展示球队的界面。然后点击…...

自制Windows系统(十)

上图 &#xff08;真的不是Windows破解版&#xff09; 开源地址&#xff1a;仿Windows...

World of Warcraft /script SetRaidTarget(“target“, n, ““) n=8,7,6,5,4,3,2,1,0

魔兽世界执行当前目标标记方法 /script SetRaidTarget("target", n, "") n8,7,6,5,4,3,2,1,0 解析这个lua脚本 D:\Battle.net\World of Warcraft\_classic_\Interface\AddOns\wMarker wMarker.lua /script SetRaidTarget("target", 8, &quo…...

Rust中Tracing 应用指南

欢迎来到这篇全面的Rust跟踪入门指南。Rust 的tracing是一个用于应用程序级别的诊断和调试的库。它提供了一种结构化的、异步感知的方式来记录日志和跟踪事件。与传统的日志记录相比&#xff0c;tracing能够更好地处理复杂的异步系统和分布式系统中的事件跟踪&#xff0c;帮助开…...

海外媒体发稿:根据您的要求编写二十个文案标题方法-华媒舍

本文旨在科普解读并描述标题中所包含的二十个爆款文案&#xff0c;为读者提供更深入的了解和知识。通过对每个标题进行拆解描述&#xff0c;我们将深入探讨各个文案标题的背后含义和吸引人之处。 1、"10个你不可忽视的秘密技巧&#xff0c;提升你的生活品质&#xff01;&q…...

gitlab:使用脚本批量下载项目,实现全项目检索

目的 当需要知道gitlab中所有项目是否存在某段代码时&#xff0c;gitlab免费版只提供了当个项目内的检索&#xff0c;当项目过多时一个个查太过繁琐。下面通过 GitLab API 将指定 Group 下的所有项目克隆到本地。此脚本会自动获取项目列表并逐一克隆它们&#xff0c;再在本地进…...

macos 使用 nvm 管理 node 并自定义安装目录

系统环境&#xff1a;MacOS Version 参考文章&#xff1a; Github 地址&#xff1a;https://github.com/nvm-sh/nvm 安装的方式是很简单的&#xff0c;直接执行下面的命令即可&#xff1a; curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bas…...

网络编程第一课

0voice第一课 https://github.com/0voice 今日学习&#xff1a;网络通信IO 网络通信的核心是通过系统提供的socket套接字实现的。socket和c语言中文件操作的本质类似&#xff0c;在c语言中&#xff0c;通过fopen、fclose、fread、fwrite实现了对文件的操作&#xff0c;socket…...

玩转 Burp Suite (1)

内容预览 ≧∀≦ゞ 玩转 Burp Suite (1)声明Burp Suite 简介Dashboard&#xff08;仪表盘&#xff09;1. 默认任务管理2. 暂停任务3. 新建扫描任务4. 使用总结 Target&#xff08;目标&#xff09;1. SIte Map &#xff08;站点地图&#xff09;2. Scope&#xff08;范围&#…...

【linux】(16)date命令

基本用法 date [OPTION]... [FORMAT]显示当前日期和时间 默认情况下&#xff0c;date 命令显示当前的日期和时间&#xff1a; date输出示例&#xff1a; Sun Jun 2 10:29:08 UTC 2024自定义日期和时间格式 可以使用 FORMAT 选项自定义输出格式。常用的格式选项包括&#…...

算法笔记:并查集

一、什么是并查集 并查集的逻辑结构是一个包含N个元素的集合&#xff0c;如图&#xff1a; 我们将各个元素划分为若干个互不相交的子集&#xff0c;如图&#xff1a; 二、并查集的基本操作 &#xff08;一&#xff09;初始化 初始化可以先将每个子集指向自己 //初始化int []…...

密码系统设计实验3-2

文章目录 《密码系统设计》实验实验项目实验三 密码模块实现4-6 学时实践要求&#xff08;30 分&#xff09; 《密码系统设计》实验 实验项目 实验序号实验名称实验学时数实验目的实验内容实验类型学生学习预期成果实验三密码模块实现6基于商用密码标准的密码模块的实现实现简…...

Spring Boot 与 Spring Cloud Alibaba 版本兼容对照

版本选择要点 Spring Boot 3.x 与 Spring Cloud Alibaba 2022.0.x Spring Boot 3.x 基于 Jakarta EE&#xff0c;javax.* 更换为 jakarta.*。 需要使用 Spring Cloud 2022.0.x 和 Spring Cloud Alibaba 2022.0.x。 Alibaba 2022.0.x 对 Spring Boot 3.x 的支持在其发行说明中…...

SVD 奇异值分解

SVD 是一种矩阵分解和降维的算法&#xff0c;通过分解矩阵找到奇异值&#xff0c;奇异值越大代表特征越重要。公式如下 A U Σ V T A U \Sigma V^T AUΣVT U : 左矩阵 ( m \times m ) Σ \Sigma Σ: 对角奇异值矩阵V&#xff1a;右矩阵( n \times n ) Sklearn 实现 S…...

C++设计模式-享元模式

动机(Motivation) 在软件系统采用纯粹对象方案的问题在于大量细粒度的对象会很快充斥在系统中&#xff0c;从而带来很高的运行时代价——主要指内存需求方面的代价。如何在避免大量细粒度对象问题的同时&#xff0c;让外部客户程序仍然能够透明地使用面向对象的方式来进行操作…...

AI加持,华为全屋智能品牌升级为“鸿蒙智家”

1.传统智能家居的困境&#xff1a;从便利到繁琐 近年来&#xff0c;智能家居因其便捷性和科技感受到消费者的青睐。然而&#xff0c;随着用户需求的多样化&#xff0c;传统智能家居的弊端逐渐显现&#xff1a; 设备连接复杂&#xff0c;品牌间兼容性不足&#xff0c;用户不得不…...

洛谷刷题之p1631

序列合并 题目入口 题目描述 有两个长度为 N N N 的单调不降序列 A , B A,B A,B&#xff0c;在 A , B A,B A,B 中各取一个数相加可以得到 N 2 N^2 N2 个和&#xff0c;求这 N 2 N^2 N2 个和中最小的 N N N 个。 输入格式 第一行一个正整数 N N N&#xff1b; 第二…...

uniapp前端开发,基于vue3,element plus组件库,以及axios通讯

简介 UniApp 是一个基于 Vue.js 的跨平台开发框架&#xff0c;旨在通过一次开发、编译后运行在多个平台上&#xff0c;如 iOS、Android、H5、以及小程序&#xff08;微信小程序、支付宝小程序、百度小程序等&#xff09;等。UniApp 为开发者提供了统一的开发体验&#xff0c;使…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)

说明&#xff1a; 想象一下&#xff0c;你正在用eNSP搭建一个虚拟的网络世界&#xff0c;里面有虚拟的路由器、交换机、电脑&#xff08;PC&#xff09;等等。这些设备都在你的电脑里面“运行”&#xff0c;它们之间可以互相通信&#xff0c;就像一个封闭的小王国。 但是&#…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段&#xff1a; 构建阶段&#xff08;Build Stage&#xff09;&#xff1a…...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

自然语言处理——Transformer

自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效&#xff0c;它能挖掘数据中的时序信息以及语义信息&#xff0c;但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN&#xff0c;但是…...

深度学习习题2

1.如果增加神经网络的宽度&#xff0c;精确度会增加到一个特定阈值后&#xff0c;便开始降低。造成这一现象的可能原因是什么&#xff1f; A、即使增加卷积核的数量&#xff0c;只有少部分的核会被用作预测 B、当卷积核数量增加时&#xff0c;神经网络的预测能力会降低 C、当卷…...

Yolov8 目标检测蒸馏学习记录

yolov8系列模型蒸馏基本流程&#xff0c;代码下载&#xff1a;这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中&#xff0c;**知识蒸馏&#xff08;Knowledge Distillation&#xff09;**被广泛应用&#xff0c;作为提升模型…...

GitHub 趋势日报 (2025年06月06日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...

Python Einops库:深度学习中的张量操作革命

Einops&#xff08;爱因斯坦操作库&#xff09;就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库&#xff0c;用类似自然语言的表达式替代了晦涩的API调用&#xff0c;彻底改变了深度学习工程…...

Spring Boot + MyBatis 集成支付宝支付流程

Spring Boot MyBatis 集成支付宝支付流程 核心流程 商户系统生成订单调用支付宝创建预支付订单用户跳转支付宝完成支付支付宝异步通知支付结果商户处理支付结果更新订单状态支付宝同步跳转回商户页面 代码实现示例&#xff08;电脑网站支付&#xff09; 1. 添加依赖 <!…...