这个程序运行结果会是什么?

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 多线程问题的知识点的更多相关文章

  1. java多线程-概念&创建启动&中断&守护线程&优先级&线程状态(多线程编程之一)

    今天开始就来总结一下Java多线程的基础知识点,下面是本篇的主要内容(大部分知识点参考java核心技术卷1): 1.什么是线程以及多线程与进程的区别 2.多线程的创建与启动 3.中断线程和守护线程以及 ...

  2. Java多线程的下载器(1)

    实现了一个基于Java多线程的下载器,可提供的功能有: 1. 对文件使用多线程下载,并显示每时刻的下载速度. 2. 对多个下载进行管理,包括线程调度,内存管理等. 一:单个文件下载的管理 1. 单文件 ...

  3. Java多线程编程实战指南(核心篇)读书笔记(五)

    (尊重劳动成果,转载请注明出处:http://blog.csdn.net/qq_25827845/article/details/76730459冷血之心的博客) 博主准备恶补一番Java高并发编程相 ...

  4. Java最重要的21个技术点和知识点之JAVA多线程、时间处理、数据格式

    (四)Java最重要的21个技术点和知识点之JAVA多线程.时间处理.数据格式  写这篇文章的目的是想总结一下自己这么多年JAVA培训的一些心得体会,主要是和一些java基础知识点相关的,所以也希望能 ...

  5. java多线程知识点

    下面是我学习多线程记录的知识点,并没详细讲解每个知识点,只是将重要的知识点记录下来,有时间可以看看,如果有不对的地方,欢迎大家指出,谢谢! 1.多线程的状态和创建方式:     线程的状态:      ...

  6. Java多线程学习(五)线程间通信知识点补充

    系列文章传送门: Java多线程学习(二)synchronized关键字(1) Java多线程学习(二)synchronized关键字(2) Java多线程学习(三)volatile关键字 Java多 ...

  7. Java 多线程与并发【知识点笔记】

    Java 多线程与并发[知识点笔记] Java多线程与并发 先说一下线程与进程的由来: 在初期的计算机,计算机只能串行执行任务,并且需要长时间的等待用户的输入才行 到了后来,出现了批处理,可以预先将用 ...

  8. java 多线程——一个定时调度的例子

    java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...

  9. Java Tread多线程(0)一个简单的多线程实例

    作者 : 卿笃军 原文地址:http://blog.csdn.net/qingdujun/article/details/39341887 本文演示,一个简单的多线程实例,并简单分析一下线程. 编程多 ...

随机推荐

  1. Hadoop2.6.0伪分布式搭建

    环境: 1.Ubuntu14.04 首先要在linux系统上新建一个账户,比如就叫做hadoop,用于专门运行hadoop. 2.配置jdk 我是使用的版本是jdk1.8. 解压:创建/usr/jav ...

  2. 写一篇Hook Driver.

    关于Hook,有一本书讲的比较清楚,最近刚刚看完,<Rootkits: Subverting the Windows Kernel> http://www.amazon.com/Rootk ...

  3. [HDU6304][数学] Chiaki Sequence Revisited-杭电多校2018第一场G

    [HDU6304][数学] Chiaki Sequence Revisited -杭电多校2018第一场G 题目描述 现在抛给你一个数列\(A\) \[ a_n=\begin{cases}1 & ...

  4. text-overflow使用文字超多div的宽度或超过在table中<td>

    关键字:text-overflow:ellipsis 语法:text-overflow:clip | ellipsis 取值 clip:默认值.不显示省略标记(...),而是简单的裁切. ellips ...

  5. hdu 1787 GCD Again (欧拉函数)

    GCD Again Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...

  6. [洛谷P3195][HNOI2008]玩具装箱TOY

    题目大意:有n个物体,大小为$c_i$.把第i个到第j个放到一起,容器的长度为$x=j-i+\sum\limits_{k-i}^{j} c_k$,若长度为x,费用为$(x-L)^2$.费用最小. 题解 ...

  7. 在C/C++函数中使用可变参数

    原文链接地址:http://blog.csdn.net/djinglan/article/details/8425768 下面介绍在C/C++里面使用的可变参数函数. 先说明可变参数是什么,先回顾一下 ...

  8. BZOJ2001 [Hnoi2010]City 城市建设 【CDQ分治 + kruskal】

    题目链接 BZOJ2001 题解 CDQ分治神题... 难想难写.. 比较朴素的思想是对于每个询问都求一遍\(BST\),这样做显然会爆 考虑一下时间都浪费在了什么地方 我们每次求\(BST\)实际上 ...

  9. bzoj2724: [Violet 6]蒲公英 分块 区间众数 论algorithm与vector的正确打开方式

    这个,要处理各个数的话得先离散,我用的桶. 我们先把每个块里的和每个块区间的众数找出来,那么在查询的时候,可能成为[l,r]区间的众数的数只有中间区间的众数和两边的数. 证明:若不是这里的数连区间的众 ...

  10. 设置edittext的样式

    1.在res->drawable编写 <?xml version="1.0" encoding="utf-8"?> <shape xml ...