IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> 多线程下变量传参与常量传参的可见性分析 -> 正文阅读

[移动开发]多线程下变量传参与常量传参的可见性分析

多线程中操作对象的话,该对象的变化对其它线程是不可见的吗?经过测试,答案是否定的。JVM在执行方法时,将方法信息压到方法栈,压入对象时,压的是对象的引用,而非对象的值。

在这里插入图片描述

案例一:

多线程,对象传参:

package cn.test.Tread.MethodStackTest;

import lombok.Data;

@Data
public class People {

  public String name;
  public int age;
  People(String name1,int age1){
    this.name=name1;
    this.age=age1;
  }
}
package cn.test.Tread.MethodStackTest;


public class Thread1 extends Thread{
  People people;
  Thread1(People people1){
    this.people = people1;
  }
  @Override
  public void run() {
    int i = people.getAge();
    try {
      Thread.sleep(500);
    }catch (InterruptedException e){
      
    }
    people.setAge(people.getAge()+1);
    while(++i!=people.getAge() && i<10000) {
      System.out.println(this.getClass().toString()+"i:"+i+";age:"+people.getAge() );
    }
  }

}
package cn.test.Tread.MethodStackTest;

import org.springframework.beans.factory.annotation.Autowired;

public class MethodStackTest {

  public static boolean b = true;
  public static void main(String args[]) {
    People people=new People("11",1);
    Thread1 thread1 = new Thread1(people);
    thread1.start();
    while(people.getAge()<10000){
      people.setAge(people.getAge()+1);
    }
  }

}

执行结果:

class cn.test.Tread.MethodStackTest.Thread1i:1058;age:10001
class cn.test.Tread.MethodStackTest.Thread1i:1059;age:10001
class cn.test.Tread.MethodStackTest.Thread1i:1060;age:10001
class cn.test.Tread.MethodStackTest.Thread1i:1061;age:10001
class cn.test.Tread.MethodStackTest.Thread1i:1062;age:10001
class cn.test.Tread.MethodStackTest.Thread1i:1063;age:10001
...

可以看出,多线程入栈后,在外部操作变量对线程内可见。

案例二:

那么,如果操作常量会是什么效果呢?

package cn.test.Tread.MethodStackTest;

public  class Thread2 extends Thread {
  Boolean b;
  Thread2(Boolean b1){
    b=b1;
  }
  @Override
  public void run() {
    b = false;
  }
}
package cn.test.Tread.MethodStackTest;


public class MethodStackInnerClassTest {

  public static boolean b =true;
  public static void main(String args[]) {
    People people = new People("zx", 29);

    Thread2 thread2 = new Thread2(b);
    thread2.start();
    while (b) {
      System.out.println("变量未更新");
    }
    System.out.println("变量已更新");
  }

}

此处运行结果,会进入死循环。

可以看出,多线程入栈后,在外部操作常量对线程内不可见。

这是因为变量在方法栈的是【地址】,而常量在方法栈的是【值】。(都是值传递,只是变量传的是地址值)

案例三:

那么,什么情况操作常量,可以对线程间可见呢?有一种场景,就是静态常量。将案例二略微修改一下:

package cn.test.Tread.MethodStackTest;

public  class Thread2 extends Thread {

  @Override
  public void run() {
    MethodStackInnerClassTest.b = false;
  }
}
package cn.test.Tread.MethodStackTest;

public class MethodStackInnerClassTest {
  public static boolean b =true;
  public static void main(String args[]) {
    People people = new People("zx", 29);

    Thread2 thread2 = new Thread2(b);
    thread2.start();
    while (b) {
      System.out.println("变量未更新");
    }
    System.out.println("变量已更新");
  }

}

执行结果:

变量未更新
变量已更新

既然方法栈中存的是变量引用,那么导致多线程可见性的原因是什么呢?

因为缓存。CPU与RAM之间,存在多级缓存,这就导致了缓存数据没有及时更新产生的可见性问题。

参考链接:

java基础之对象当做参数传进方法的堆栈内存解析 - 青衫仗剑 - 博客园https://www.cnblogs.com/blazezzz/p/9103575.htmlJava多线程 可见性问题出现的原因_Java持续实践-CSDN博客_java多线程可见性问题文章目录可见性问题出现的原因可见性问题出现的原因主要的原因可以从下图中分析出来.此图中, 最下层为ram, 也就是内存, 而内存离CPU之间 ,是有多级的缓存的.L3 cache为内存的一部分, 会把内存中高频用到的部分缓存起来.L2 cache为L3 cache的一部分, 会把L3 cache高频用到的部分缓存起来.L1 cache为L2 cache的一部分, 会把L2 cache高频用到的部分缓存起来.每一层缓存的大小在缩小, 但读取速度在不断的增加.到了Register 是寄存器,https://blog.csdn.net/qq_33229669/article/details/108421939

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-03-13 21:56:51  更:2022-03-13 21:58:55 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年10日历 -2024/10/26 18:16:06-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码