将AtomicInteger对象作为方法的局部变量, 传递给其他线程, 读写操作是否是线程安全的?

场景

在main线程中, 有一个方法名为triggerSomeThreadWithMethodLocalVariable, 该方法会启动一些线程并且带着该方法里的一个类型为AtomicInteger的局部变量(一般写代码是把线程共享的变量作为类的成员变量),每个线程对该变量的局部变量atomicInteger进行写操作, atomicInteger变量是否在线程间持续可见并且线程安全?

代码

 /**
* @author rhyme
*/
@Slf4j
public class MethodLocalVariableMain {
public static void main(String[] args) {
final MethodLocalVariableMain methodLocalVariableMain = new MethodLocalVariableMain();
final AtomicInteger atomicInteger = new AtomicInteger(10);
methodLocalVariableMain.triggerSomeThreadWithMethodLocalVariable(atomicInteger);
} public void triggerSomeThreadWithMethodLocalVariable(AtomicInteger atomicInteger) {
final int threadCount = 10;
CompletableFuture[] completableFutures = new CompletableFuture[threadCount];
for (int i = 0; i < threadCount; i++) {
completableFutures[i] =
CompletableFuture.runAsync(
() -> {
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
log.error("InterruptedException happen when TimeUnit.SECONDS.sleep(3);", e);
Thread.currentThread().interrupt();
}
log.info(
"ThreadName: {}, atomicInteger.decrementAndGet(): {}.",
Thread.currentThread().getName(),
atomicInteger.decrementAndGet());
});
} // 等待所有CompletableFuture线程执行完毕
CompletableFuture.allOf(completableFutures).join();
log.info(
"In main thread, after all completableFuture is finished, threadName: {}, atomicInteger.get(): {}.",
Thread.currentThread().getName(),
atomicInteger.get());
}
}

上述代码流程见上面的"场景"描述.

运行结果

在4核8逻辑处理测试结果如下:

ThreadName: ForkJoinPool.commonPool-worker-1, atomicInteger.decrementAndGet(): 3.
ThreadName: ForkJoinPool.commonPool-worker-7, atomicInteger.decrementAndGet(): 5.
ThreadName: ForkJoinPool.commonPool-worker-3, atomicInteger.decrementAndGet(): 6.
ThreadName: ForkJoinPool.commonPool-worker-6, atomicInteger.decrementAndGet(): 4.
ThreadName: ForkJoinPool.commonPool-worker-2, atomicInteger.decrementAndGet(): 9.
ThreadName: ForkJoinPool.commonPool-worker-5, atomicInteger.decrementAndGet(): 7.
ThreadName: ForkJoinPool.commonPool-worker-4, atomicInteger.decrementAndGet(): 8.
ThreadName: ForkJoinPool.commonPool-worker-3, atomicInteger.decrementAndGet(): 0.
ThreadName: ForkJoinPool.commonPool-worker-7, atomicInteger.decrementAndGet(): 2.
ThreadName: ForkJoinPool.commonPool-worker-1, atomicInteger.decrementAndGet(): 1.
In main thread, after all completableFuture is finished, threadName: main, atomicInteger.get(): 0.

总结

根据结果来看, 被main线程方法传递的atomicInteger变量, 它的value属性在新启动的各个线程是线程安全, 并且value持续可见;

原理是, 传递的是atomicInteger变量的引用, 即多个线程持有的是同一份atomicInteger变量的引用, 并且利用了AtomicInteger的特性(CAS修改被volatile修饰的变量value, 对value操作的原子性以及变量value在多线程间的可见性);

虽然结果是正确的, 但是还是不建议这样使用方法的局部变量, 这样可能会发生线程逃逸等问题;

线程之间的共享变量, 还是应该作为对象的成员变量更好, 这才是常见的规范写法.

将AtomicInteger对象作为方法的局部变量, 传递给其他线程, 读写操作是否是线程安全的?的更多相关文章

  1. Activity传递对象的方法

    //Serializeable传递对象的方法 public void SerializeMethod(){ Person mPerson = new Person(); mPerson.setName ...

  2. java类(Class)的概念;对象的概念,声明类的属性 和方法,局部变量和成员变量,面向对象编程思维,抽象的概念

    类(Class)的概念 类是对一组具有相同特征和行为的对象的抽象描述. 理解: [1] 类包含了两个要素:特性和行为 => 同一类事物具有相同的特征和行为. [2] 类是一个群体性概念.例如:网 ...

  3. request对象的方法及其参数的传递

    先设计一个简单的登录界面index.htm: <html><head><title>request的使用</title></head>< ...

  4. 【java】值传递和引用传递---对象作为方法的参数传入属于哪种传递

    首先 这篇作为一个永久性的问题,欢迎大家讨论 其次,个人结论如下几条: ①Java有且只有一种传递,即 值传递 ②作为方法的参数传入,都是对原本的实参进行了copy ③只不过[实参]若是[基本数据类型 ...

  5. 《Java从入门到失业》第四章:类和对象(4.4):方法参数及传递

    4.4方法参数及传递 关于这个知识点,我想了很久该不该在这里阐述.因为这个知识点稍微有点晦涩,并且就算不了解也不影响用Java编写代码.不过笔者刚开始工作的时候,就是因为这块内容没有过多的关注,以至于 ...

  6. 面向对象、类与对象、成员与局部变量、封装、private、构造函数、this、static、extends、super、final、abstract、interface、多态、内部类、异常【5】

    若有不正之处,请多多谅解并欢迎批评指正,不甚感激. 请尊重作者劳动成果: 本文原创作者:pipi-changing本文原创出处:http://www.cnblogs.com/pipi-changing ...

  7. 1、探究java方法参数传递——引用传递?值传递!

    原创博文,转载请注明出处.谢谢~~ java程序运行时,其对象是怎么进行放置和安排的呢?内存是怎么分配的呢?理解好这个很有好处!java有5个地方可以存储数据: 1.寄存器.这是最快的存储区,位于处理 ...

  8. JS中的对象和方法简单剖析

    众所周知,在js中对象就是精髓,不理解对象就是不理解js. 那么什么事js中的对象呢? 在js中,几乎一切皆对象: Boolean ,String,Number可以是对象(或者说原生数据被认作对象): ...

  9. Java中类,对象,方法的内存分配

    Java中类,对象,方法的内存分配 以下针对引用数据类型: 在内存中,类是静态的概念,它存在于内存中的CodeSegment中. 当我们使用new关键字生成对象时,JVM根据类的代码,去堆内存中开辟一 ...

  10. Objective-C之成魔之路【7-类、对象和方法】

    郝萌主倾心贡献,尊重作者的劳动成果,请勿转载. 假设文章对您有所帮助,欢迎给作者捐赠.支持郝萌主,捐赠数额任意,重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载:点我传送 Objec ...

随机推荐

  1. 时间工具类之“LocalDateTime方案转换地域性时差问题->本地时间 转 UTC时间

    一.使用方法 1.这里有使用LocalDateTime,Date, 2.直接使用LocalDateTime来将输入时间转为UTC还是没有摸索到,看了下源码发现根据偏移量去处理的,但是没有测试成功所以换 ...

  2. Grid 布局-容器项

    grid 网格布局是一个用于web的二维布局系统, 多行多列. flex 单行布局则更倾向于一维布局, 一行或者一列. Grid 重点 只是用表格进行排版哈, 横向内容直接无关联哦. 容器项 子项 布 ...

  3. CV中常用Backbone-3:Clip/SAM原理以及代码操作

    前面已经介绍了简单的视觉编码器,这里主要介绍多模态中使用比较多的两种backbone:1.Clip:2.SAM.对于这两个backbone简单介绍基本原理,主要是讨论使用这个backbone. 1.C ...

  4. 字符型union注入

    注入目标和思路:拿到库名---拿到表名---拿到列名---拿到用户名和密码 用 id=1' order by x --+ 来确定表有几列,然后用 id=0' union select x1,x1,x3 ...

  5. Hoic对网站的测试使用

    禁止使用该项技术攻击一切未经允许的公网网站,违者将受到法律制裁. 下载地址:https://wwl.lanzout.com/iiJa11zsqljg 下载完成后解压,并打开. 打开 \(hoic2.1 ...

  6. java-web与jdbc 的使用

    1:本地连接数据库的步骤 1 public class LoginDao { 2 3 // jdbc操作的五部曲 4 5 // 1: 导入jar包 6 // 2: 加载驱动 7 // 3: 获取连接 ...

  7. 《Java基础——JDK的下载、安装以及环境变量的配置》

    Java基础--JDK的下载.安装以及环境变量的配置 一.JDK的下载: 目前为止,JDK总共有三个LTS版本(长期支持版本) 版本 LTS时间 JDK 8 2030年12月 JDK 11 2026年 ...

  8. Jenkinsfile_配置定时任务

    triggers 在jenkinsfile来定义流水线时,常规情况下,项目都是基于手动点击部署,这种策略尤其适用于线上环境,但在测试环境,乃至于预发环境,应该对自动构建有更高的集成度,使开发者只关注于 ...

  9. react项目添加typescript类型定义文件 .d.ts

    最近用react + antd mobile + typescript开发项目,其中使用了rc-form这个包,可惜没有typescript版本,导致找不到类型定义. 一起来重温一下这个经典的错误. ...

  10. 袋鼠云:基于Flink构建实时计算平台的总体架构和关键技术点

    数栈是云原生-站式数据中台PaaS,我们在github和gitee上有一个有趣的开源项目:FlinkX,FlinkX是一个基于Flink的批流统一的数据同步工具,既可以采集静态的数据,也可以采集实时变 ...