变量的线程安全分析

news2025/2/2 20:48:15

目录

变量的线程安全

常见线程安全类


变量的线程安全

成员变量和静态变量是否线程安全?

如果它们没有共享,则线程安全

如果它们被共享了,根据它们的状态是否能够改变,又分两种情况

  • 如果只有读操作,则线程安全
  • 如果有读写操作,则这段代码是临界区,需要考虑线程安全

局部变量是否线程安全?

局部变量是线程安全的

但局部变量引用的对象则未必

  • 如果该对象没有逃离方法的作用访问,它是线程安全的
  • 如果该对象逃离方法的作用范围,需要考虑线程安全

局部变量线程安全分析

public static void test1() {
 int i = 10;
 i++;
}

每个线程调用 test1() 方法时局部变量 i,会在每个线程的栈帧内存中被创建多份,因此不存在共享

 局部变量的引用稍有不同

先看一个成员变量的例子

class ThreadUnsafe {
    ArrayList<String> list = new ArrayList<>();

    public void method1(int loopNumber) {
        for (int i = 0; i < loopNumber; i++) {
            { //临界区, 会产生竞态条件
                method2();
                method3();
                // } 临界区
            }
        }
    }

    private void method2() {
        list.add("1");
    }

    private void method3() {
        list.remove(0);
    }
}

执行

其中一种情况是,如果线程2 还未 add,线程1 remove 就会报错:

Exception in thread "Thread0" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
	at java.util.ArrayList.rangeCheck(ArrayList.java:659)
	at java.util.ArrayList.remove(ArrayList.java:498)
	at com.cc.db.ThreadUnsafe.method3(Gun.java:35)
	at com.cc.db.ThreadUnsafe.method1(Gun.java:24)
	at com.cc.db.ThreadUnsafe.lambda$main$0(Gun.java:16)
	at java.lang.Thread.run(Thread.java:750)

分析: 无论哪个线程中的 method2 引用的都是同一个对象中的 list 成员变量

method3 与 method2 分析相同

 将 list 修改为局部变量

class ThreadSafe {
    public final void method1(int loopNumber) {
        ArrayList<String> list = new ArrayList<>();
        for (int i = 0; i < loopNumber; i++) {
            method2(list);
            method3(list);
        }
    }

    private void method2(ArrayList<String> list) {
        list.add("1");
    }

    private void method3(ArrayList<String> list) {
        list.remove(0);
    }
}

那么就不会有上述问题了

分析:

  • list 是局部变量,每个线程调用时会创建其不同实例,没有共享
  • 而 method2 的参数是从 method1 中传递过来的,与 method1 中引用同一个对象
  • method3 的参数分析与 method2 相同

 

方法访问修饰符带来的思考,如果把 method2 和 method3 的方法修改为 public 会不会代理线程安全问题?

情况1:有其它线程调用 method2 和 method3

情况2:在 情况1 的基础上,为 ThreadSafe 类添加子类,子类覆盖 method2 或 method3 方法,即

常见线程安全类

  • String
  • Integer
  • StringBuffer
  • Random
  • Vector
  • Hashtable
  • java.util.concurrent 包下的类

这里说它们是线程安全的是指,多个线程调用它们同一个实例的某个方法时,是线程安全的。也可以理解为

Hashtable table = new Hashtable();
 

new Thread(()->{
 table.put("key", "value1");
}).start();
 

new Thread(()->{
 table.put("key", "value2");
}).start();
  • 它们的每个方法是原子的
  • 但注意它们多个方法的组合不是原子的 

线程安全类方法的组合

分析下面代码是否线程安全?

Hashtable table = new Hashtable();
// 线程1,线程2
if( table.get("key") == null) {
 table.put("key", value);
}

 即线程1判为空以后,并没有立刻put进去数据,而线程2这个时候也进行了判空,马上进行了put数据。线程1这时才put数据

不可变类线程安全性

String、Integer 等都是不可变类,因为其内部的状态不可以改变,因此它们的方法都是线程安全的 有同学或许有疑问,String 有 replace,substring 等方法【可以】改变值啊,那么这些方法又是如何保证线程安 全的呢?

Java中的String类是不可变类,这意味着一旦创建String对象,它的值就无法更改。因此,对于String对象的任何操作都不会影响原始对象,而是创建并返回一个新的String对象。

对于replace和substring等方法,实际上是返回了一个新的字符串对象,而不是在原始的字符串对象上进行修改,所以这样的操作不会引起线程安全问题。

具体来说,在Java中,String类的任何方法都是线程安全的,因为String类对象本身是不可变的,即String类的实例字段都声明为final类型,这些实例字段的值一旦被初始化后便无法更改,同时这些实例字段也没有提供任何可以修改它们的方法。因此,多个线程可以同时访问并共享同一个String对象,而不需要担心线程安全问题。

需要注意的是,如果在多线程环境下使用StringBuilder类或StringBuffer类,则需要采取相应的线程安全措施,因为它们是可变的字符串类,可能会引起线程安全问题。例如,可以使用synchronized关键字对StringBuilder类或StringBuffer类的共享代码块进行同步,或者使用ThreadLocal使得每个线程都拥有自己的StringBuilder或StringBuffer实例。

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

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

相关文章

【30天熟悉Go语言】7 Go流程控制之分支结构if、switch

文章目录 一、前言二、if1、单分支Go语法规范&#xff1a; 2、双分支Go语法规范 3、多分支 三、switch1、基本语法2、语法规范1&#xff09;switch2&#xff09;case3&#xff09;default 四、总结 一、前言 Go系列文章&#xff1a; GO开篇&#xff1a;手握Java走进Golang的世界…

手机APP大用户并发测试

一、背景 随着智能手机近年来的快速增长&#xff0c;从游戏娱乐到移动办公的各式各样的手机APP软件渗透到我们的生活中&#xff0c;对于大型的手机APP测试不仅要关注它的功能性、易用性还要关注它的性能&#xff0c;最近发现LoadRunner12可以对手机APP做性能测试&#xff0c;但…

寻味一座城,从吃吃吃开始

点击文末“阅读原文”即可参与节目互动 剪辑、音频 / 小黑 运营 / SandLiu 卷圈 监制 / 姝琦 文案 / 小黑 产品统筹 / bobo 场地支持 / 声湃轩天津站 为了再也不用在节目里喊“我们真的不是美食节目”&#xff0c;2023年7月起&#xff0c;原汤话原食将更名为“记者下班”…

记录--极致舒适的Vue可编辑表格

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 使用ElementPlus的Table啥都好&#xff0c;就是没有可编辑表格&#xff01;&#xff01;&#xff01;&#x1f62d; 既然UI库不支持&#xff0c;那我们实现一个可编辑表格是很难的事么&#xff1f;&am…

Avalon 学习系列(五)—— 过滤器

Avalon 本身有很多过滤器&#xff0c;例如 date、number等文本过滤器、循环过滤器&#xff1b;avalon 也提供了方法可以根据需求自定义过滤器。 示例&#xff1a; &#xff08;1&#xff09;定义一个 myFunc 的个性化过滤器&#xff0c;并加在元素上&#xff1b; &#xff0…

一文带你玩转 RustChinaConf 2023,内含赞助商展位活动福利和 Workshop 介绍

除了两天干货满满的会议外&#xff0c;RustChinaConf 的赞助商也准备了精美的周边礼物等待大家去打卡。每位参会者在签到的时候会获得一张集章卡&#xff0c;集齐上面所有的章&#xff0c;可至签到处兑换精美礼物一份。偷偷剧透一下&#xff0c;奖品有大家喜欢的 Rust 小螃蟹玩…

【计算机网络】第一章 概述(上)

文章目录 第一章 概述1.2 因特网概述1.2.1 网络、互连网&#xff08;互联网&#xff09;和因特网1.2.2 因特网发展的三个阶段1.2.4 因特网的组成 1.3 三种交换方式1.3.1 电路交换1.3.2 分组交换1.3.3 报文交换1.3.4 三种方式对比 1.4 计算机网络的定义 第一章 概述 1.2 因特网概…

「深度学习之优化算法」笔记(二)优化算法的分类

1. 优化算法的分类 1.1常见的优化算法 在分类之前&#xff0c;我们先列举一下常见的优化算法&#xff08;不然我们拿什么分类呢&#xff1f;&#xff09; 1.遗传算法Genetic algorithm 2.粒子群优化算法Particle Swarm Optimization 3.差分进化算法Differential Evolution 4.人…

springboot第27集:springboot-mvc,WxPay

在数据库中&#xff0c;DISTINCT 关键字用于查询去重后的结果集。它用于从查询结果中去除重复的行&#xff0c;只返回唯一的行。 要使用 DISTINCT 关键字&#xff0c;可以将其放置在 SELECT 关键字之前&#xff0c;指示数据库返回去重后的结果。 请注意&#xff0c;DISTINCT 关…

Linux常用命令——getenforce命令

在线Linux命令查询工具 getenforce 显示当前SELinux的应用模式&#xff0c;是强制、执行还是停用。 补充说明 grename命令可以重命名卷组的名称。 语法 getenforce例子 查看当前SELinux的应用模式。 [rootlocalhost ~]# getenforce Enforcing在线Linux命令查询工具 原文…

ChatGPT时代,我的新书《智慧共生》上市了

告诉你一个好消息&#xff0c;我在人民邮电出版社的第二本书《智慧共生&#xff1a;ChatGPT 与 AIGC 生产力工具实践》刚刚上市&#xff0c;你现在就可以在 京东 和 当当买到了。 有人把 2022 年称作 AIGC&#xff08;人工智能生成内容&#xff09; 的元年&#xff0c;我深表赞…

浅谈数据中台之数据开发

目 录 01 前言‍ 02 中台概念及背景 ‍‍‍‍‍‍‍ 03 数据中台建设方法‍‍‍‍‍‍ 04 数据开发实践 01‍ 前言‍‍ 2015年阿里在国内首次提出了中台概念&#xff0c;由阿里引领发展&#xff0c;迅速在互联网企业中形成了一股浪潮。在数字化转型的道路上&#xff0c;为了…

【AUTOSAR】UDS协议的代码分析与解读(五)----ECU诊断服务

8 诊断服务 8.1 总览 此章节定义了本规范中可使用的诊断服务及其执行规则。 下表列出了h事业部定义的所有UDS诊断服务。ECU最终实现与下述定义不符之处必须得到h事业部 的认可。服务实现内容需在零部件诊断规范中详细说明。 表 9 诊断服务支持列表 诊断服务列表 APP Bootlo…

【手撕代码】同步 FIFO、LIFO/Stack

FIFO 是FPGA设计中最有用的模块之一。FIFO 在模块之间提供简单的握手和同步机制&#xff0c;是设计人员将数据从一个模块传输到另一个模块的常用选择。 在这篇文章中&#xff0c;展示了一个简单的 RTL 同步 FIFO&#xff0c;可以直接在自己的设计中配置和使用它&#xff0c;该设…

社区供稿 | RLHF 实践中的框架使用与一些坑 (TRL, LMFlow)

1 前言 之前看见文章总结了常见的一些 RLHF 框架的经验, 但是似乎没看见 Hugging Face 自己维护的 TRL 库的相关文章, 正好最近调 TRL 比较多, 就想写一个文章分享一下使用过程中踩到的坑&#xff0c;另外也介绍一下我们的全流程框架 LMFlow 。 LMFlow 框架示意图。 我们主要用…

架构思维的六要素

很多人都在私信问我随着ChatGPT等技术的兴起&#xff0c;自己的饭碗会不会没了。我的观点是&#xff1a;ChatGPT能做的工作十几年前早就没了。 十几年前还看到过招聘广告上写招程序员的&#xff0c;现在都是工程师起步&#xff0c;工程师是要有架构思维的。 像十几年前的黄金时…

手写SpringBoot启动器主要步骤

这里写目录标题 背景过程2.1自启动实现原理2.2手动实现SpringBoot自启动2.2.1宏观2.2.1微观2.2.1.1三个服务之间调用2.2.1.2自定义注解2.2.1.1业务组装2.2.1.3启动类 升华自定义注解&#xff1a;手动装配组件&#xff1a;简化启动过程&#xff1a;自动化注入依赖&#xff1a;简…

马原第三章复习1.

唯物史观和唯心史观过去出过小题 社会意识出小题 社会存在一般出大题 124 社会存在和社会意识(往往出大题) 社会历史性的基本问题 两种根本对立的历史史观 唯心主义: 至多考察人的思想动机 没有考虑思想背后的物质动因和经济根源 把社会史观看成人的思想,,不懂得…

关于酒店宾馆电气火灾隐患的预防与整改措施介绍 安科瑞 许敏

摘要&#xff1a;本文分析了酒店、宾馆电气火灾隐患的特点及产生的主要原因&#xff0c;并依此提出了消除火灾隐患的整改措施。 关键词:酒店宾馆&#xff1b;火灾&#xff1b;隐患&#xff1b;预防&#xff1b;整改&#xff1b;措施 1前言 随着旅居服务业的快速发展&#xf…

CVPR 2023 | 香港理工提出GrowSP:3D场景的无监督语义分割

点击下方卡片&#xff0c;关注“CVer”公众号 AI/CV重磅干货&#xff0c;第一时间送达 点击进入—>【目标检测和Transformer】交流群 GrowSP: Unsupervised Semantic Segmentation of 3D Point Clouds 论文链接&#xff1a;https://arxiv.org/abs/2305.16404 代码&#xff1…