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. Python 学习日记 第八天
  2. Dreamweaver 2020安装教程
  3. python多线程实现同步的方式_深入解析Python中的线程同步方法
  4. Pandas处理数据太慢,来试试Polars吧!
  5. 芋道 spring security oauth2 入门_Spring官方宣布:新的Spring OAuth2.0授权服务器已经来了
  6. 腾讯2021春季校园招聘启动
  7. 便携式办公套件LibreOffice Portable 4.0.1
  8. 产品经理如何搞定客户和业务
  9. 将Nginx加入service服务中
  10. [android游戏编程之从零开始].李华明,AndroidGameSourc
  11. android播放器录制视频,Android播放器的录制实践
  12. c语言数据域和指针域,C语言的变量域和指针
  13. Java实现Unicode和中文相互转换
  14. 自定义video的controls(播放暂停按钮、进度条、快进快退等)
  15. 计算机硬盘根目录是什么,硬盘根目录是什么意思?存放哪里?
  16. 做电商网站服务器在哪里,电商网站服务器如何选择
  17. 【springboot】jasypt加密
  18. 【莫烦Python】Numpy教程
  19. android 免费游戏推荐,10款免费Android小游戏推荐
  20. SQL 通配符及其使用

热门文章

  1. Linux 多线程(二)线程安全:线程安全、互斥与互斥锁、死锁、同步与条件变量
  2. 使用mybatis-generator自动生成代码的方法介绍及踩坑
  3. QUIC实战(二) AWS 搭建nginx(http3.0) + upsync + consul(server-client模式) 集群
  4. C语言登顶!|2021年7月编程语言排行榜
  5. 使用VMware VSphere WebService SDK进行开发 (一)——基本信息阐述
  6. 【推荐】技术人必看的音视频学习资源清单
  7. 音视频技术开发周刊 | 213
  8. 数据结构与算法之完全二叉树的节点个数
  9. 国产数据库领域屡次率先突破,腾讯TDSQL亮相CNCC 2019!
  10. Serverless——前端的3.0时代