1.Java的内存模型

Java Memory Model (JAVA 内存模型)描述线程之间如何通过内存(memory)来进行交互。 具体说来, JVM中存在一个主存区(Main Memory或Java Heap Memory),对于所有线程进行共享,而每个线程又有自己的工作内存(Working Memory),工作内存中保存的是主存中某些变量的拷贝,线程对所有变量的操作并非发生在主存区,而是发生在工作内存中,而线程之间是不能直接相互访问,变量在程序中的传递,是依赖主存来完成的。

2、内存可见性

从上图可知,如果线程A对共享变量X进行了修改,但是线程A没有及时把更新后的值刷入到主内存中,而此时线程B从主内存读取共享变量X的值,所以X的值是原始值,那么我们就说对于线程B来讲,共享变量X的更改对线程B是不可见的。
例如:

public class NoVisibility{private static boolean asleep = true;private static class readerThread extends Thread{while(!asleep){doSomething();}}public static void main(String []args){new readerThread().start();asleep = false;}
}

当主线程把asleep改成true时,这个new readerThread()可能会继续循环下去,因为主线程的asleep的结果储存在他的本地内存中,而没有刷新到主内存中,所以new readerThread()读取主内存,根本没有察觉到asleep的变化。

3.如何实现可见?

实现可见有四类关键字,volatile,java.util.concurrent中实现的原子操作类,synchronized,还有final

volatile

volatile赋予了变量可见——禁止编译器对成员变量进行优化,它修饰的成员变量在每次被线程访问时,都强迫从内存中重读该成员变量的值;而且,当成员变量发生变化时,强迫线程将变化值回写到共享内存,这样在任何时刻两个不同线程总是看到某一成员变量的同一个值,这就是保证了可见性。简单来说就是读必须从主内存读,写必须写到主内存中。

由于使用volatile屏蔽掉了VM中必要的代码优化,所以在效率上比较低,因此一定在必要时才使用此关键字。 就跟C中的一样 禁止编译器进行优化。

使用建议:
1.在上面的asleep状态变量的例子中,非常适合用volatile关键字,它用来检测某个状态变量以判断是否进行下一步操作。它常常用做中断或状态的标志

2.当要访问的变量已在synchronized代码块中,或者为final时,不必使用。原因很简单,因为synchronized和final都能让变量可见

synchronized

synchronized的可见性是由“对一个变量执行unlock操作之前,必须先把此变量同步回主内存中(执行store和write操作)”这条规则获得的。

Java.util.concurrent中实现的原子操作类

Java.util.concurrent中实现的原子操作类包括:
AtomicBoolean、AtomicInteger、AtomicLong、AtomicReference。
 
其底层就是volatile和CAS 共同作用的结果:

  • 首先使用了volatile 保证了内存可见性。
  • 然后使用了CAS(compare-and-swap)算法 保证了原子性。
    其中CAS算法的原理就是里面包含三个值:内存值A 预估值V 更新值 B 当且仅当 V == A 时,V = B; 否则,不会执行任何操作。

final

被final修饰的字段是构造器一旦初始化完成,并且构造器没有把“this”引用传递出去,那么在其它线程中就能看见final字段的值。

Java多线程之线程的可见性(二)相关推荐

  1. Java多线程之线程池配置合理线程数

    Java多线程之线程池配置合理线程数 目录 代码查看公司服务器或阿里云是几核的 合理线程数配置之CPU密集型 合理线程数配置之IO密集型 1. 代码查看公司服务器或阿里云是几核的 要合理配置线程数首先 ...

  2. Java多线程:线程安全和非线程安全的集合对象

    转载自  Java多线程:线程安全和非线程安全的集合对象 一.概念: 线程安全:就是当多线程访问时,采用了加锁的机制:即当一个线程访问该类的某个数据时,会对这个数据进行保护,其他线程不能对其访问,直到 ...

  3. java多线程方式轮询,深入理解JAVA多线程之线程间的通信方式

    一,介绍 本总结我对于JAVA多线程中线程之间的通信方式的理解,主要以代码结合文字的方式来讨论线程间的通信,故摘抄了书中的一些示例代码. 二,线程间的通信方式 ①同步 这里讲的同步是指多个线程通过sy ...

  4. 初学Java多线程:线程简介

     Java多线程初学者指南系列教程http://developer.51cto.com/art/200911/162925.htm 初学Java多线程:线程简介 2009-06-29 17:49 ...

  5. java多线程及线程池使用

    Java多线程及线程池的使用 Java多线程 一.Java多线程涉及的包和类 二.Java创建多线程的方式 三.Java线程池 1. 创建线程池ThreadPoolExecutor的7个参数 2. 线 ...

  6. Java多线程之线程同步机制(锁,线程池等等)

    Java多线程之线程同步机制 一.概念 1.并发 2.起因 3.缺点 二.三大不安全案例 1.样例一(模拟买票场景) 2.样例二(模拟取钱场景) 3.样例三(模拟集合) 三.同步方法及同步块 1.同步 ...

  7. Java多线程02(线程安全、线程同步、等待唤醒机制)

    Java多线程2(线程安全.线程同步.等待唤醒机制.单例设计模式) 1.线程安全 如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运行结果和单线程运行的结果是一样的,而且其他的变量 ...

  8. Java多线程之线程池的手写改造和拒绝策略

    Java多线程之线程池的手写改造和拒绝策略 目录 自定义线程池的使用 四种拒绝策略代码体现 1. 自定义线程池的使用 自定义线程池(拒绝策略默认AbortPolicy) public class My ...

  9. Java多线程之线程池7大参数、底层工作原理、拒绝策略详解

    Java多线程之线程池7大参数详解 目录 企业面试题 线程池7大参数源码 线程池7大参数详解 底层工作原理详解 线程池的4种拒绝策略理论简介 面试的坑:线程池实际中使用哪一个? 1. 企业面试题 蚂蚁 ...

最新文章

  1. 干货 | 漫谈图神经网络
  2. 学会python之后-学会Python后,人生简直开挂了!
  3. 4.3 matlab常用的特殊图形(条形图、直方图、饼图、散点图等)
  4. abstract类_走进C# abstract,了解抽象类与接口的异同
  5. 第一行代码 Android (郭霖 著)
  6. 20200327:最大矩形(leetcode85)
  7. android 通过html设置textview的内容不同种颜色
  8. file标签选择文件change事件失效处理方法
  9. 深度学习实现工业零件的缺陷检测
  10. windows redis 设置密码_Linux下设置redis访问密码
  11. qq linux五笔输入法下载软件,qq五笔输入法2017
  12. 利用电影直播赚钱的方法(几乎零成本、很多人不知道)
  13. ios 边录音边放_iOS 录音、音频的拼接剪切以及边录边压缩转码
  14. java判断接口地址是否存在_java.util.Iterator接口中的hashNext()方法是用来判断集合中是否存在下一个元素的()_学小易找答案...
  15. 王道机试 第十二章 动态规划 12.5 背包问题(0-1背包,完全背包,多重背包)
  16. 如何用adb命令启动安装的APK
  17. 7天从代码入门到开发应用,怎样快速提高代码能力?
  18. 学习Android闹钟源代码(三)-AlarmClock类分析(part2)
  19. Android Room使用
  20. windows安装OHS(weblogic管理)

热门文章

  1. (一)boost库之日期、时间
  2. cocos2d-x游戏实例(6)-A星算法(2)
  3. 网络编程释疑之:TCP半开连接的处理
  4. STL 之search,search_n,sort,binary_search
  5. python之多线程编程(一):基本介绍
  6. 设计模式:命令模式(Command)
  7. 音视频技术开发周刊 | 161
  8. LiveVideoStackCon 2020 首届音视频线上峰会【优秀出品人与讲师】
  9. ffmpeg内存模型及AVPacket和AVFrame API基本使用
  10. 腾讯海量存储与CDN的自动化运维