并发编程 03:对象的共享
并发编程 02:线程安全性
线程安全性
在构建文件的并发程序时,必须正确地使用线程和锁,但这些终归只是一些机制。要编写线程安全的代码,其核心在于要对状态访问操作进行管理,特别是对共享的和可变的状态的访问。一个对象是否是线程安全的,取决于它是否被多个线程同时访问。当多个线程访问某个状态变量并且其中有一个线程执行写入操作时,必须采用同步机制来协同这些线程对变量的访问。Java中的主要同步机制是关键字synchronized,它提供了一种独占的加锁方式,但「同步」这个术语还包括volatile类型的变量,显式锁以及原子变量。
如果当多个线程访问同一个可变的状态变量时没有使用合适的同步,那么程序就会出现错误。有三种方式可以修复这个问题:
- 不在线程之间共享该状态变量
- 将状态变量改为不可变的变量
- 在访问状态变量时使用同步
什么是线程安全性
当多个线程访问某个类时,不管运行时环境采用何种调度方式或者这些线程将如何交替执行,并且在主调代码中不需要任何额外的同步或协同,这个类都能表现出正确的行为,那么就称这个类是线程安全的。在线程安全类中封装了必要的同步机制,因此客户端无须进一步采取同步措施。
无状态对象一定是线程安全的。(没有共享数据)
并发编程 01:核心概念介绍
在看完了《深入理解Java虚拟机》之后,继续看《Java并发编程实战一书》。
相信在了解虚拟机之后,再来看并发相关知识,能理解得更透彻,书中也讲到,对Java内存模型理解得越深入,就对并发编程掌握得越好。顺道说一下,关于JDK里线程和并发相关类的使用,我主要是通过《Think in Java》学习的,这里就不再介绍基本使用方法了。
简介
线程也被称为轻量级进程(这一部分在《深入理解Java虚拟机》中提到过,点击查看)。在大多数现代操作系统中, 都是以线程为基本的调度单位,而不是进程。
线程的优势
要想充分发挥多处理器系统的强大计算能力,线程可以有效的降低程序的开发和维护成本,同时提升复杂应用程序的性能。
JVM深入理解 12:Java内存模型与线程
JVM深入理解 11:晚期编译优化
「内存模型」可以理解为在特定的操作协议下,对特定的内存或高速缓存进行读写访问的过程抽象。
Java内存模型
Java虚拟机规范中试图定义一种Java内存模型来屏蔽掉各种硬件和操作系统内存访问差异,以实现让Java程序在各种平台下都能达到一致的内存访问效果。在此之前,主流程序语言(如C/C++等)直接使用物理硬件和操作系统的内存模型,因此,会由于不同平台上内存模型的差异,有可能导致程序在一套平台上并发完全正常,而在另外一台平台上并发访问却经常出错,因此在某些场景就必须针对不同的平台来编写程序。
主内存与工作内存
Java内存模型的主要目标是定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节。此处的变量与Java编程中所说的变量有所区别,它包括了实例字段、静态字段和构成数组对象的元素,但不包括局部变量与方法参数,因为后者是线程私有的,不会被共享,自然不存在竞争问题。
Java内存模型规定了所有的变量都存储在主内存中,每条线程还有自己的私有工作内存,线程的工作内存中保存了被该线程使用到的变量的主内存副本拷贝,线程对变量的所有操作都必须在工作内存中进行。不同的线程之间也无法直接访问对方工作内存中的变量,线程间变量值的传递均需要通过主内存来完成。(这很好的诠释了volatile关键字的作用和原理)
JVM深入理解 10:早期编译优化
Java程序最初是通过解释器进行解释执行的,当虚拟机发现某个方法或代码块的运行特别频繁时,就会把这些代码认定为『热点代码』。为了提高热点代码的执行效率,在运行时,虚拟机将会把这些代码编译成与本地平台相关的机器码,并进行各种层次的优化,完成这个任务的编译器称为即时编译器。
HotSpot虚拟机内的即时编译器
解释器与编译器
HotSpot虚拟机是采用解释器与编译器并存的架构。解释器和编译器各有优势:当程序需要迅速启动和执行的时候,解释器可以首先发挥作用,省去编译的时间,立即执行。在程序运行后,随着时间的推移,编译器逐渐发挥作用,把越来越多的代码编译成本地代码之后,可以获取更高的执行效率。
编译对象与触发条件
在运行过程中被即时编译器编译的『热点代码』有两类:
- 被多次调用的方法
- 被多次执行的循环体
JVM深入理解 09:类加载及执行子系统的案例与实战
执行引擎是Java虚拟机最核心的组成部分之一,本章将主要从概念模型的角度来讲解虚拟机的方法调用和字节码执行。
运行时栈帧结构
栈帧(Stack Frame)是用于支持虚拟机进行方法代用和方法执行的数据结构,它是虚拟机运行时数据区中的虚拟机栈的栈元素。栈帧存储了局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用开始至执行完成的过程,都对应着一个栈帧在虚拟机里面从入栈到出栈的过程。对于执行引擎来说,在活动线程中,只有位于栈顶的栈帧才是有效的,称为当前栈帧,与这个栈帧相关联的方法称为当前方法,执行引擎运行的所有字节码指令都只针对当前栈帧进行操作,在概念模型上,典型的栈帧结构图如下:
