Java并发--内存结构图及线程安全

内存结构图

内存-> (开辟的数组) -> (方法区,堆,栈,程序计数器,本地方法栈)

:几乎所有的对象实例都在这里分配内存。堆中每个对象的头信息都标属着他属于哪个类。

方法区它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编译器编译后的代码缓存等数据

的区域很小,只有1M,特点是存取速度很快,所以在stack中存放的都是快速执行的任务,基本数据类型的数据,和对象的引用(reference),方法的拷贝运行。只有处于栈顶的方法才处于运行状态,其他的属于就绪状态。

本地方法栈:栈中方法拷贝运行时,因为底层时c语言的方法,所以需要本地方法栈,来翻译方法,使之成为操作系统本身的内核方法,对接驱动。

每个线程启动的时候,都会创建一个PC(Program Counter,程序计数器)寄存器。PC寄存器里保存有当前正在执行的JVM指令的地址

小例子:

w,e的指向确实改变了,但是没有影响到x1,x2。

什么是Class常量池?

  • 我们写的每一个**Java类被编译后,就会形成一份Class文件** ;Class文件除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池表(Constant Pool Table),用于存放编译期生成的各种字面量与符号引用

  • 每一个Class文件中都有一个Class常量池

被编译后的类就会进入Class常量池

IO操作

IO操作,就是将数据写入内存或从内存输出的过程,也指应用程序和外部设备之间的数据传递。

常见IO流操作,一般指内存与磁盘间的输入输出流操作。

final关键字

1.对象构造函数内有final域,必须先用构造函数构造对象,再把对象赋给其他引用 2.如果对象有final域,必须先读对象的引用,再读final域。

这两个规则的目的是保证:在对象引用为任意线程可见之前,对象的final域已经被正确初始化过了,而普通域就不具有这个保障。

请看下面的Java代码,它定义了一个类Person,有两个域:name和age。name是一个final域,age是一个非final域。然后,它创建了一个Person对象,并在另一个线程中读取它的域。

复制代码
c
java 复制代码
lass Person {
    final String name; // final域
    int age; // 非final域
public Person(String name, int age) {
    this.name = name; // 写final域
    this.age = age; // 写非final域
}
}
​
public class Test {
    static Person person;
    public static void main(String[] args) throws InterruptedException {
    Thread t1 = new Thread(new Runnable() {
        @Override
        public void run() {
            person = new Person("Alice", 20); // 把对象引用赋值给person
        }
    });
    Thread t2 = new Thread(new Runnable() {
        @Override
        public void run() {
            if (person != null) { // 读对象引用
                System.out.println(person.name); // 读final域
                System.out.println(person.age); // 读非final域
            }
        }
    });
    t1.start();
    t2.start();
    t1.join();
    t2.join();
}
}
复制代码

根据final的重排序规则,线程t2在读取person.name时,一定能看到正确的值Alice,因为写final域和赋值对象引用之间不能重排序。但是,线程t2在读取person.age时,可能看到的不是正确的值20,而是0,因为写非final域和赋值对象引用之间可以重排序。这就是final和非final域的区别

使用多线程可能会带来的问题

并发编程的目的就是为了能提高程序的执行效率提高程序运行速度,但是并发编程并不总是能提高程序运行速度的,而且并发编程可能会遇到很多问题,比如:内存泄漏、死锁、线程不安全等等。

如何理解线程安全不安全?

线程安全和不安全是在多线程环境下对于同一份数据的访问是否能够保证其正确性和一致性的描述。

  • 线程安全指的是在多线程环境下,对于同一份数据,不管有多少个线程同时访问,都能保证这份数据的正确性和一致性。

  • 线程不安全则表示在多线程环境下,对于同一份数据,多个线程同时访问时可能会导致数据混乱、错误或者丢失。

相关推荐
无限的鲜花几秒前
反射(原创推荐)
java·开发语言
IT二叔16 分钟前
Java项目部署-03-teamcity-cicd-docker镜像流水线方式部署
java·ci/cd·持续部署
yongche_shi28 分钟前
ragas官方文档中文版(五十)
开发语言·python·ai·ragas·如何评估和改进 rag 应用
一路向北he32 分钟前
字节钢铁军团--“提供情境,而非控制”
java·开发语言·前端
超级数据查看器1 小时前
超级数据查看器 v10.0 发布
java·大数据·数据库·sqlite·安卓
AI行业学习2 小时前
Notepad++ 官方下载 + 完整安装 + 全套优化配置(2026最新)
开发语言·人工智能·python·前端框架·html·notepad++
折哥的程序人生 · 物流技术专研2 小时前
《Java 100 天进阶之路》第50篇:阻塞队列与并发容器(2026版)
java·面试题·java进阶·blockingqueue·并发容器·集合源码·java100天进阶
ai_coder_ai3 小时前
编写自动化脚本,在自己后端服务中使用Open Api进行设备相关操作
java·运维·自动化
大圣编程3 小时前
Python中continue语句的用法是什么?
开发语言·前端·python
硕风和炜3 小时前
【LeetCode: 2492. 两个城市间路径的最小分数 + DFS】
java·算法·leetcode·深度优先·dfs·bfs·并查集