摘要: 参考:http://developer.51cto.com/art/200906/126363.htm http://www.cnblogs.com/feisky/archive/2010/03/21/1691170.html1 下载eclipseeclipse:http://eclipse.org... 阅读全文
posted @ 2015-03-18 19:52 王超_cc 阅读(207) 评论(0) 推荐(0) 编辑

Java内存模型

简述

Java虚拟机规范中试图定义一种Java内存模型(Java Memory Model,JMM)来屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一致的内存访问效果。

定义模型的目标

Java内存模型的主要目标是定义程序中各个变量的访问规则,即在虚拟机中将变量存储到内存和从内存中取出变量这样的底层细节。
这里说的变量包括实例字段、静态字段和构成数组对象的元素不包括局部变量与方法参数,因为后者是线程私有的,不会共享,也就不存在竞争的问题。


 

  Java 面向对象编程 P96

每当用java命令启动一个java虚拟机进程时,Java虚拟机就会创建一个主线程,该线程从程序入口main()方法开始执行。主线程在Java栈区内有一个方法调用栈,每执行一个方法,就会向方法调用栈中压入一个包含该方法的局部变量以及参数的栈帧、

主线程首先把main()方法的栈帧压入方法调用栈,在这个栈帧中包含四个param局部变量 ,当主线程开始执行changeParameter()方法时,会把该方法的栈帧也压入方法调用栈。在这个栈帧中包含四个param参数,它们的初始值由main()方法的四个param局部变量传递。

图3-15显示了主线程开始准备执行changeParameter()方法时方法调用栈的状态。

查看代码
/**
 * P96 例程 3-5 ParamTester.java*/
public class ParamTester {
	public int memberVariable = 0;	//成员变量
	
	public static void main(String[] args) {
		//声明并初始化4个局部变量
		int param1 = 0;			//param1是基本数据类型
		ParamTester param2 = new ParamTester();		//param2是引用对象类型
		ParamTester param3 = new ParamTester();		//param3是引用对象类型
		int [] param4 = {0};						//param4是数组引用类型
		
		//将四个局部变量作为参数传递给changeParameter()方法
		changeParameter(param1,param2,param3,param4);
		
		//打印四个局部变量
		System.out.println("param1="+param1);
		System.out.println("param2.memberVariable="+param2.memberVariable);
		System.out.println("param3.memberVariable="+param3.memberVariable);
		System.out.println("param4[0]="+param4[0]);
	}
	
	public static void changeParameter(int param1,ParamTester param2,ParamTester param3,int[] param4) {
		param1 = 1;	//改变基本数据类型参数的值
		param2.memberVariable = 1;	//改变对象类型参数的实例变量
		param3 = new ParamTester();	//改变对象类型参数的引用,使它引用一个新对象
		param3.memberVariable = 1 ;	//改变新的对象的实例变量
		param4[0] = 1;				//改变数组类型参数的元素
	}
}

 

13.1 Java线程的运行机制 P365
在JAVA虚拟机中,执行程序代码的任务主要是由线程来完成的。每个线程都有一个独立的程序计数器和方法调用栈.

*  程序计数器:也成为PC寄存器,当线程执行一个方法时,程序计数器指向方法中下一条要执行的字节码指令。

* 方法调用栈: 简称方法栈,用来跟踪线程中一系列的方法调用过程,栈中的元素称为栈帧。每当程序调用一个方法的时候,就会向方法栈压入一个新帧。帧用来存储方法的参数,局部变量和运算过程中的临时数据

帧由以下三个部分组成:
* 局部变量区: 存放局部变量和局部参数。
* 操作数栈: 是线程的工作区,用来存放运算过程中生成的临时数据。
* 栈数据区: 为线程执行指令提供相关的信息,包括如何定位到堆区和方法区的特定数据,以及如何正常退出方法或者异常中断方法。

每当用java命令启动一个Java虚拟机进程时,Java虚拟机都会创建一个主线程,该线程从程序入口main()方法开始执行。
下面以例程13-1的Sample为例,介绍线程的运行过程。

查看代码
//P365 例程 13-1 Sample.java
public class Sample {
	private int a;		//实例变量
	public int method() {
		int b = 0;	//局部变量
		a++;
		b=a;
		System.out.println("this.a   "+this.a);
		return b;
	}
	
	public static void main(String[] args) {
		Sample s = null;		//局部变量
		int a = 0;			//局部变量
		
		s = new Sample();
		a=s.method();
		System.out.println(a);
	}
}




主内存与工作内存

Java内存模型规定了所有的变量都存储在主内存(Main Memory)中,此外每条线程还有自己的工作内存(Working Memory)。

线程的工作内存中保存了被该线程使用到的变量的主内存副本拷贝,线程对变量的所有操作(读取、赋值等)都必须在工作内存中进行,不能直接读写主内存中的变量。

并且,不同的线程之间也无法直接访问对方工作内存中的变量,线程间变量值得传递均需要通过主内存来完成,线程、主内存、工作内存关系如下图:

也可以把这里的主内存与工作内存概念与JVM运行时数据区进行对应,主内存主要对应Java堆中的对象实例数据部分,工作内存对应于虚拟机栈中的部分区域

内存间的交互动作

动作 作用

lock

(锁定)

作用于主内存变量,把一个变量标示为一条线程独占的状态

unlock

(解锁)

作用于主内存的变量,把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定

read

(读取)

作用于主内存的变量,把一个变量的值从主内存传输到线程的工作内存中,以便随后的load动作使用

load

(载入)

作用于工作内存的变量,把read操作从主存中得到的变量值放入工作内存的变量副本中

use

(使用)

作用于工作内存的变量,把工作内存中一个变量的值传递给执行引擎,每当虚拟机遇到一个需要使用到变量的值的字节码指令时将会执行这个操作

assign

(赋值)

作用于工作内存的变量,把一个从执行引擎接收到的值赋给工作内存中的变量,每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作

store

(存储)

作用于工作内存的变量,把工作内存中一个变量的值传送到主内存中,以便随后的write操作使用

write

(写入)

作用于主内存的变量,把store操作从工作内存中得到的变量的值放入主内存的变量中

 

 

posted @ 2021-12-24 17:41 王超_cc 阅读(16) 评论(0) 推荐(0) 编辑
摘要: ThreadLocal原理解析与注意事项 以下是对原文的备注以及修订 原文: Entry数据结构 ThreadLocalMap维护了一个Entry类型的数据结构: static class Entry extends WeakReference<ThreadLocal<?>> { /** The v 阅读全文
posted @ 2021-12-17 15:23 王超_cc 阅读(64) 评论(0) 推荐(0) 编辑
摘要: 笔记一: 1 static class ThreadLocalMap { 2 ... 3 * The table, resized as necessary. 4 * table.length MUST always be a power of two. 5 */ 6 private Entry[] 阅读全文
posted @ 2021-12-17 12:25 王超_cc 阅读(35) 评论(0) 推荐(0) 编辑
摘要: Java 8 ThreadLocal 源码解析 原文几处备注如下: 原文写到: 源码解析 我们从ThreadLocal.set方法开始分析:.... 每个 Thread 对象维护了一个 ThreadLocalMap 类型的 threadLocals 字段。 ThreadLocalMap 的 key 阅读全文
posted @ 2021-12-16 21:32 王超_cc 阅读(191) 评论(0) 推荐(0) 编辑
摘要: JAVA存储机制(栈、堆、方法区详解) - SegmentFault 思否一、JAVA的六种存储地址 寄存器 register位于处理器内部,是最快的储存器,但是数量极其有限。由编译器根据需求进行分配,不能由代码控制,对于开发者来说是 无感知 的。 堆栈 stack位于RAM中,堆栈指针下移分配新的 阅读全文
posted @ 2021-07-02 16:12 王超_cc 阅读(1547) 评论(0) 推荐(2) 编辑
摘要: 原文: UltraEdit(代码编辑器) v28.10.0.26 64位中文绿色已激活版 在上述页面最末 找到如下下载链接 下载后 安装软件文件为: ues_chinese_64.exe 双击直接安装即可(此安装过程可设置安装路径) 无需手动破解,无试用期限,安装完成即可使用。 阅读全文
posted @ 2021-06-07 11:54 王超_cc 阅读(22261) 评论(0) 推荐(0) 编辑
摘要: 什么叫互为质数-质数是什么-数学学习资料 我们把只有“1”这一个公约数的两个整数称为互为质数 例如2与3互为质数 3与5互为质数 互为质数简称“互质” 提示: 也就是两个数之间没有除1以外的公因数称为互质; 类似问题 类似问题1:什么是互为质数[数学科目] 两个自然数中只有公约数1的,这两个数称为互 阅读全文
posted @ 2021-06-06 17:33 王超_cc 阅读(6968) 评论(0) 推荐(0) 编辑
摘要: 原文: 图解排序算法(二)之希尔排序 基本思想 希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。 简单插入排序很循规蹈矩,不管数组分布是怎么样的,依然一步一步的对元素进行比较,移动,插 阅读全文
posted @ 2021-06-05 17:05 王超_cc 阅读(62) 评论(0) 推荐(0) 编辑
摘要: 原文: eclipse如何自动补全设置-百度经验 (baidu.com) 1 首先打开eclipse,上面菜单栏中有一个window选项 2 点击“window",在弹出的菜单中点击“preferences" 3 然后在"preferences"页面,点击“Java” 4 然后在“java”分类中, 阅读全文
posted @ 2021-06-04 15:52 王超_cc 阅读(3744) 评论(0) 推荐(0) 编辑
摘要: https://www.cnblogs.com/winsker/p/6728672.html 移位运算符操作的对象就是二进制的位,可以单独用移位运算符来处理int型整数。 以int类型的6297为例,代码如下: 运行结果: 1100010011001 111111111111111111100111 阅读全文
posted @ 2019-03-09 09:50 王超_cc 阅读(380) 评论(0) 推荐(0) 编辑
点击右上角即可分享
微信分享提示