一个关于Java 多线程问题的知识点
这个程序运行结果会是什么?
public class Main {static class ListAdd {
private static List list = new ArrayList();
public void add() {
list.add("baoer");
}
public int size() {
return list.size();
}
}
public static void main(String[] args) throws IOException {
final ListAdd list = new ListAdd();
new Thread(new Runnable() {
@Override
public void run() {
try {
for (int i= ; i < ; i++) {
Thread.sleep(500);
list.add();
System.out.println("线程:" + Thread.currentThread().getName() + " 添加了一个元素" );
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"T1").start();
new Thread(new Runnable() {
@Override
public void run() {
while (true) {
if (list.size()== ) {
System.out.println("当前线程收到通知 " + Thread.currentThread().getName() + " list.size=5线程停止");
throw new RuntimeException();
}
}
}
}, "T2").start();
// fun();
}
如果知道ArrayList不是线程安全的也许答案就是线程T1运行结束,T2一直执行下去不会抛出异常而结束。事实结果也确是这样。但这样的执行结果背后却值得深思。
问题1:这是因为有可能T2线程某次读入缓存的size为4,但下一次读入缓存的数字是6,所以永远进入不了if.
但由于线程T1每次add之后都sleep 500 毫秒所以这种可能不存在。
问题2:在T2 if(list.size() == 5) 之前将size放入一个Hashset发现Hashset中只有一个值 0 。这说明size根本没有从主内存中刷新到T2工作内存中,为什么主存中size值都更新了还不刷新到工作内存中呢?不是有缓存一致性吗?
原因就是 T2中的size根本没有在T2的缓存中!这是编译器干的事! 编译器发现是一个while(true),并且要频繁使用size,就会把size放在寄存器中提高访问速度,缓存不保存size。所以即使有缓存一致性size永远无法更新。
问题3: 为什么list是volatile 就会得到正确结果?
对于volatile变量 编译器不会把它放入寄存器中,在缓存中volatile 可以保证可见性,并且根据happens-before规则 volatile 的读取一定在写入之后。
问题4: 为什么在if判断前加 System.out.println(list.size()); 也会的到正确结果?
通过查看System.out.println 源码发现执行输出语句时要加同步锁,
JMM关于synchronized的两条规定:
1. 线程解锁前,必须把共享变量的最新值刷新到主内存中
2. 线程加锁时,先清空工作内存中共享变量的值,从而使用共享变量时需要从主内存中重新读取最新的值。
由于清空工作内存中的值所以寄存器中的值也失效了,虽然此时值没在工作内存中,但也寄存器也会刷新再从工作内存中读取。
问题5: 为什么在if判断前加Thread.sleep(0)或者Thread.yield();也会的到正确结果?
这涉及到了线程的上下文切换,一但切换上下文工作内存中的就值就会失效,系统保存了线程的状态,下次切换回来时重新从内存中读值。
一个关于Java 多线程问题的知识点的更多相关文章
- java多线程-概念&创建启动&中断&守护线程&优先级&线程状态(多线程编程之一)
今天开始就来总结一下Java多线程的基础知识点,下面是本篇的主要内容(大部分知识点参考java核心技术卷1): 1.什么是线程以及多线程与进程的区别 2.多线程的创建与启动 3.中断线程和守护线程以及 ...
- Java多线程的下载器(1)
实现了一个基于Java多线程的下载器,可提供的功能有: 1. 对文件使用多线程下载,并显示每时刻的下载速度. 2. 对多个下载进行管理,包括线程调度,内存管理等. 一:单个文件下载的管理 1. 单文件 ...
- Java多线程编程实战指南(核心篇)读书笔记(五)
(尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/76730459冷血之心的博客) 博主准备恶补一番Java高并发编程相 ...
- Java最重要的21个技术点和知识点之JAVA多线程、时间处理、数据格式
(四)Java最重要的21个技术点和知识点之JAVA多线程.时间处理.数据格式 写这篇文章的目的是想总结一下自己这么多年JAVA培训的一些心得体会,主要是和一些java基础知识点相关的,所以也希望能 ...
- java多线程知识点
下面是我学习多线程记录的知识点,并没详细讲解每个知识点,只是将重要的知识点记录下来,有时间可以看看,如果有不对的地方,欢迎大家指出,谢谢! 1.多线程的状态和创建方式: 线程的状态: ...
- Java多线程学习(五)线程间通信知识点补充
系列文章传送门: Java多线程学习(二)synchronized关键字(1) Java多线程学习(二)synchronized关键字(2) Java多线程学习(三)volatile关键字 Java多 ...
- Java 多线程与并发【知识点笔记】
Java 多线程与并发[知识点笔记] Java多线程与并发 先说一下线程与进程的由来: 在初期的计算机,计算机只能串行执行任务,并且需要长时间的等待用户的输入才行 到了后来,出现了批处理,可以预先将用 ...
- java 多线程——一个定时调度的例子
java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...
- Java Tread多线程(0)一个简单的多线程实例
作者 : 卿笃军 原文地址:http://blog.csdn.net/qingdujun/article/details/39341887 本文演示,一个简单的多线程实例,并简单分析一下线程. 编程多 ...
随机推荐
- python基础之获取版本信息
在工作中经常会需要确定使用的py的版本信息,以便适配更多的系统,达到更大的兼容性. 一般关于python的信息和参数都要调用sys模块,关于操作系统的信息和调用都要使用os模块 所以这次我们使用sys ...
- android多点触控自由对图片缩放
在系统的相册中,观看相片就可以用多个手指进行缩放. 要实现这个功能,只需要这几步: 1.新建项目,在项目中新建一个ZoomImage.java public class ZoomImageView e ...
- lintcode-52-下一个排列
52-下一个排列 给定一个整数数组来表示排列,找出其之后的一个排列. 注意事项 排列中可能包含重复的整数 样例 给出排列[1,3,2,3],其下一个排列是[1,3,3,2] 给出排列[4,3,2,1] ...
- 列数不固定时怎么使用el-tabel展示数据
<el-table :data="contents" stripe> <el-table-column v-for="(item, index) in ...
- Java使用泛型的困顿
原文有点儿胡说的意味,删了,有空再次更新这篇博文~
- Java进阶
Java进阶(一)Annotation(注解) Java进阶(二)当我们说线程安全时,到底在说什么 Java进阶(三)多线程开发关键技术 Java进阶(四)线程间通信方式对比 Java进阶(五)NIO ...
- 用AngularJS操作DOM
在angular中使用第三方插件时最好都封装到指令(directives)中去,DOM操作也最好都解构到指令中. <!DOCTYPE html> <html lang="e ...
- hdu 2838 Cow Sorting (树状数组)
Cow Sorting Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- [UOJ#351]新年的叶子
[UOJ#351]新年的叶子 试题描述 躲过了AlphaGo 之后,你躲在 SingleDog 的长毛里,和它们一起来到了AlphaGo 的家.此时你们才突然发现,AlphaGo 的家居然是一个隐藏在 ...
- [Leetcode] Best time to buy and sell stock 买卖股票的最佳时机
Say you have an array for which the i th element is the price of a given stock on day i. If you were ...