java线程安全

本文是我的学习记录,里面的内容参考了王宝令老师在极客时间上的专栏:java并发编程,图片都是用的王老师的图片。为避免版权问题,任何人不得转载和发布。

在java编程世界中,最令人感到沮丧和兴奋的事莫过于多线程并发编程,其中的线程安全问题是重中之重。一般我们讨论的线程安全问题都是针对于共享变量而言的,而且这也是多线程编程相对复杂的地方,这方面的讨论可以说是汗牛充栋,多如牛毛。相对于共享变量而言,线程中的局部变量是线程安全的,编程也相对简单,这是为什么呢?下面从jvm、操作系统和cpu角度来试着说明白这件事情。

jvm对线程的处理

jvm内存区域分为方法区(Method area),堆(Heap),虚拟机栈(VM Stack),本地方法栈(Native Method Stack), 程序计数器(Program Counter Register)。其中方法区和堆为所有线程共享数据区, 虚拟机栈、本地方法栈和程序计数器为线程隔离数据区。

方法区存储虚拟机加载的类信息、常量、静态变量,以及编译器编译后的代码等数据。线程编译后的代码就存储在这儿。
堆内存堆内存主要用于存放对象(后者称之为类的实例)和数组,它是JVM管理的内存中最大的一块区域,堆内存和方法区都被所有线程共享,在虚拟机启动时创建。我们new Thread()创建一个线程实例时,是存放在推内存的。
虚拟机栈 jvm为每个线程分配一个虚拟机栈,每个虚拟机栈中都有若干个栈帧,每个栈帧中存储了局部变量表、操作数栈、动态链接、返回地址等。一个栈帧就对应Java代码中的一个方法,当线程执行到一个方法时,就代表这个方法对应的栈帧已经进入虚拟机栈并且处于栈顶的位置,每一个Java方法从被调用到执行结束,就对应了一个栈帧从入栈到出栈的过程。
也就是说,每个线程都有一个虚拟机栈,如下图:图片来自王宝令老师的极客时间专栏:java 并发编程

cpu是怎么调用的

cpu是从来不知道方法的,它是一条条机器指令执行的。编译程序把java程序编译为一条条指令,方法也是转换为一条条指令。那么怎么完成方法到指令的转换呢?当执行方法时,cpu先找到方法的地址,然后跳到这个地址执行方法的一条条指令,执行完成后,它会找到这个方法的下一条语句的地址,再跳转到这个地址去执行:图片来自王宝令老师的极客时间专栏:java 并发编程
cpu通过堆栈寄存器来找到方法的参数和方返回地址,cpu支持的这个栈是和方法调用相关的,称为调用栈。每个方法在调用栈里都有自己的独立空间,称为栈帧,每个栈帧里都有方法的参数和返回地址。当调用方法时,会创建新的栈帧,并压入调用栈;
当方法返回时,对应的栈帧就会被自动弹出;栈和方法是同生共死的。图片来自王宝令老师的极客时间专栏:java 并发编程
以上都摘自王宝令老师的专栏课程

从上面我们知道,线程的局部变量是在栈上分配的,每个线程实例都有自己独立的调用栈,参数和方法是同生共死的,两个线程实例可以用不同的参数调用相同的方法而不会产生互相干扰。

操作系统

Java中的线程和操作系统的线程是一一对应的,java中的线程实际上就是操作系统的线程。jvm把线程的调用完全交给操作系统来调度。当A线程获取cpu的时间片执行时,操作系统会把正在执行的线程B的上下文保存起来,线程B让出cpu,操作系统把线程A的上下文切进来,cpu执行线程A. 这样的一个过程就是著名的线程上下文切换,是需要时间的。所以如果一个系统有很多的线程上下文切换是非常耗时间的。

那么这个线程上下文是什么东西呢?其实上下文就是CPU的所有寄存器中的值、进程的状态以及堆栈上的内容。上面我们谈到的线帧也属于上下文的内容。由于每一个线程执行时,只会操作自己上下文里面的内容,上一个线程的上下文被保存起来,所以不同的线程数据才不会干扰。

在多核的cpu情况下,每个cpu有自己的堆栈寄存器,操作系统会调度线程跑在各个空闲出时间片的cpu上,各个在执行的线程的上下文会被切换进来。所以在多核情况下,多线程也不会造成数据混乱。

后记

再次强调,本人的博客只为自己学习使用。以上是我学习的一点体会,本人才疏学浅,很多都只是流于表面,如有不当之处,还请看到的人指正,一起提高!

后后记

在多线程情况下,实际最复杂的是共享变量的读写问题,这个才是多线程的重中之重。在这个情况下,内部处理变得非常复杂,不是一篇两篇文章能说清楚的,建议阅读“java并发编程的艺术”来彻底了解它。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值