Java学习笔记45:Java 线程与主线程之间的变量关系
运行下面的代码:
package com.test.www;public class Test {public static int count = 0;public static void inc() {//这里延迟1毫秒,使得结果明显try {Thread.sleep(1);} catch (InterruptedException e) {}count++;}public static void main(String[] args) {//同时启动1000个线程,去进行i++计算,看看实际结果for (int i = 0; i < 1000; i++) {new Thread(new Runnable() {@Overridepublic void run() {Test.inc();System.out.println(Thread.currentThread().getName());}}).start();}try {Thread.sleep(3000);} catch (Exception e){}//这里每次运行的值都有可能不同,可能为1000System.out.println("运行结果:Counter.count=" + Test.count);}
}
最后运行结果经常会变化,有时候1000,有时候999这样。
count字段添加volidate修饰,保证每次从主线程中取得的数据是最新的。但是结果还是这样?为什么呢?
public class Test {public volatile static int count = 0;public static void inc() {//这里延迟1毫秒,使得结果明显try {Thread.sleep(1);} catch (InterruptedException e) {}count++;}public static void main(String[] args) {//同时启动1000个线程,去进行i++计算,看看实际结果for (int i = 0; i < 1000; i++) {new Thread(new Runnable() {@Overridepublic void run() {Test.inc();System.out.println(Thread.currentThread().getName());}}).start();}try {Thread.sleep(3000);} catch (Exception e){}//这里每次运行的值都有可能不同,可能为1000System.out.println("运行结果:Counter.count=" + Test.count);}
}
在 java 垃圾回收整理一文中,描述了jvm运行时刻内存的分配。其中有一个内存区域是jvm虚拟机栈,每一个线程运行时都有一个线程栈,
线程栈保存了线程运行时候变量值信息。当线程访问某一个对象时候值的时候,首先通过对象的引用找到对应在堆内存的变量的值,然后把堆内存
变量的具体值load到线程本地内存中,建立一个变量副本,之后线程就不再和对象在堆内存变量值有任何关系,而是直接修改副本变量的值,
在修改完之后的某一个时刻(线程退出之前),自动把线程变量副本的值回写到对象在堆中变量。这样在堆中的对象的值就产生变化了。下面一幅图
read and load 从主存复制变量到当前工作内存
use and assign 执行代码,改变共享变量值
store and write 用工作内存数据刷新主存相关内容
其中use and assign 可以多次出现
但是这一些操作并不是原子性,也就是 在read load之后,如果主内存count变量发生修改之后,线程工作内存中的值由于已经加载,不会产生对应的变化,所以计算出来的结果会和预期不一样
对于volatile修饰的变量,jvm虚拟机只是保证从主内存加载到线程工作内存的值是最新的
例如假如线程1,线程2 在进行read,load 操作中,发现主内存中count的值都是5,那么都会加载这个最新的值
在线程1堆count进行修改之后,会write到主内存中,主内存中的count变量就会变为6
线程2由于已经进行read,load操作,在进行运算之后,也会更新主内存count的变量值为6
导致两个线程及时用volatile关键字修改之后,还是会存在并发的情况。
转载于:https://www.cnblogs.com/snake-hand/archive/2013/06/08/3127493.html
Java学习笔记45:Java 线程与主线程之间的变量关系相关推荐
- Java学习笔记:创建线程的两种方法
Java学习笔记:创建线程的两种方法 一.预备工作 1.创建Maven项目ThreadDemo 2.在pom.xml里添加依赖 二.继承Thread类创建子线程
- Java学习笔记1:Java中有关print、println、printf的用法和区别
Java学习笔记1:Java中有关print.println.printf的用法和区别 最近在学习java,写一些笔记记录下. 1.print()函数是一般的标准输出,但是不换行. 2.println ...
- handler回调主线程_Android使用Handler实现子线程与子线程、子线程与主线程之间通信...
转载:https://blog.csdn.net/shaoenxiao/article/details/54561753 今天这篇文章只讲一下怎么使用Handler实现子线程与子线程之间.子线程与主线 ...
- Java学习笔记(java基础)
Java学习笔记(第一周) Java 介绍 Java 发展方向 JVM , JDK , JRE 名词解释 Java语言的特点 Java安装 安装包的下载 配置环境变量 验证是否安装成功 Java的第一 ...
- 【java】java学习笔记之java oop(面向对象)
如下图所示为笔者总结的java oop(面向对象)学习笔记,其中,附带有代码示例(未展开),方便理解记忆.需要源文件的请到我的资源中下载,下载地址:https://download.csdn.net/ ...
- 【java】java学习笔记之java常用类
如下图所示为笔者总结的java常用类学习笔记,其中,附带有代码示例(未展开),方便理解记忆.需要源文件的请到我的资源中下载,下载地址:https://download.csdn.net/downloa ...
- Java 学习笔记(4)——java 常见类
上次提前说了java中的面向对象,主要是为了使用这些常见类做打算,毕竟Java中一切都是对象,要使用一些系统提供的功能必须得通过类对象调用方法.其实Java相比于C来说强大的另一个原因是Java中提供 ...
- Java学习笔记01—Java概述、数据类型、变量、标识符、类型转换
1. Java概述 1.1 Java语言发展史(了解) 语言:人与人交流沟通的表达方式 计算机语言:人与计算机之间进行信息交流沟通的一种特殊语言 Java语言是美国Sun公司(Stanford Uni ...
- java学习笔记(一) ----java下常用的包功能
***java下常用的包*** java.lang----包含一些java语言的核心类,如String,Math,Integer,System,Thread,提供常用的功能. java.awt---- ...
最新文章
- linux 下 jenkins 安装注意事项
- MATLAB 图像的平滑和边缘检测
- 用户不见了_屋面瓦/外墙板再也看不见螺丝打胶了
- 交叉验证(Cross Validation)方法思想简介
- 干货分享:什么是Java设计工厂模式?
- android.os.build修改,Android的os.BuildID对应的SDK版本号以及SDK版本号与APILevel对应关系.docx...
- JavaMVC之JSON
- 数值计算(Python实现)(一)
- ajax css文件,wordpress 添加JS,css文件,实现AJAX效果
- 问题二十三:C++中debug简单的运行死机问题
- php获取udid,iOS获取设备真实UDID和IMEI
- 显示计算机101代码,电脑出现蓝屏故障101停机码,怎么解决问题
- 德乐生 java_【Senior Java Developer怎么样】德乐生软件2021年Senior Java Developer前景怎么样-看准网...
- hdu-1022-Train Problem I
- 二叉树遍历的非递归实现
- 数据分析---数据处理工具pandas(二)
- 词云中去重复的词_李清照特别经典的词,把相思写得淋漓尽致,读一次心疼一次...
- 生物信息中的Markov链
- 【蓝月传奇3D】手游辅助脚本(多开/练级/日常/BOSS/活动等)
- android 横竖屏坐标转换,Android:横竖屏转换问题
热门文章
- 大数据学习01——配置虚拟机节点相关网络
- php rabbmq教程_RabbitMQ+PHP 教程一(Hello World)
- 2022-2028年中国pu管行业市场深度分析及市场规模预测报告
- 浅显易懂 Makefile 入门 (02)— 普通变量和自动变量定义、使用($@、$^、$< 作用)、变量覆盖 override、变量的来源 origin
- 机房收费系统总结【1】-整体流程
- 数据类型对应的字节数
- ADAS摄像头20个技术挑战
- GPU与CPU交互技术
- 芯片IP,SOC,FPGA智能卡
- CodeGen融合核心关系循环扩展