1. 为什么不使用volatile,其它线程也能得到变量修改后的值

实验代码分析:

①初始变量a=true,b=false;

②一个线程判断a或者b是否被改为相应逻辑,如果是,那么输出信息。

③修改a和b的线程。

实验结果分析:不是说没有volatile修饰的变量存在可见性问题吗,怎么可以得到另一个线程修改的值,不存在可见性问题吗??

原因:其实可见性问题的造成就是因为各自从缓存取数据,而不从内存取数据,如果缓存都没有数据,大家都使用内存的值,那么就不存在可见性问题。这里不存在可见性问题的原因就是当前变量还没有被放入缓存,我们可以加上一点休眠,让程序有时间把数据放入缓存,然后测试,如下。

其它博客有提到,说在线程中使用的睡眠会释放cpu执行权,然后CPU有时间去更新工作缓存和主存内容。那我这边通过一个简单的for循环,让CPU没有时间去同步缓存和主存。

2. 为什么不使用volatile,其它线程还能得到变量修改后的值

实验代码分析:

① 初始变量a=0,b=false;

②然后,一个线程判断 b 的值是否为false,是false那么循环输出“b is false and a is ”信息,直到 b 的值变为true,输出“b is true and a is”信息结束线程;

③然后延迟2ms,为了让后面的线程晚于前面线程执行;

④最后,另一个线程会修改a=1,b=true。

实验结果分析:首先控制台输出了一句“b is false and a is 0”,因为初始值a=0,b=false,所以正确;但是后面控制台输出了一句“b is true and a is 1”,为什么???不是说没有volatile修饰的变量是会存在可见性问题的吗?不是说一个线程修改的值,其它线程是得不到修改后的值吗??怎么这边能得到呢?

在分析之前,我们需要记住两点:第一,并发编程存在可见性问题;第二:可见性问题并不是只能通过volatile修饰来解决,也就是说——没有volatile修饰的变量不一定存在可见性问题

原因:既然并发编程存在可见性问题,而且这边没有volatile修饰,那么可见性问题是怎么解决的呢?其实这边可见性问题是通过System.out.println语句解决的,也就是System.out.println语句触发了MESI缓存一致性协议。我们这边将System.out.println注释后,运行结果出现了可见性问题,可验证原先是System.out.println解决了可见性问题,运行结果及分析如下。

3. 其实System.out.println是通过synchronized关键字触发MESI缓存一致性协议,从而解决可见性问题,如下图。

总结:发生可见性问题,需要两个条件,①各线程操作数据是在缓存中操作,才会存在缓存不一致;②没有触发缓存一致性协议。

为什么不使用volatile,其它线程也能得到当前线程修改后的值,不使用volatile也不存在可见性问题?原来解决可见性问题不一定需要volatile,println也可以相关推荐

  1. python线程异常中断_中断线程

    如果线程需要执行一个长时间任务,就可能需要能中断线程.中断线程就是其他线程给该线程发一个信号,该线程收到信号后结束执行run()方法,使得自身线程能立刻结束运行. 我们举个栗子:假设从网络下载一个10 ...

  2. Java多线程基础-6:线程安全问题及解决措施,synchronized关键字与volatile关键字

    线程安全问题是多线程编程中最典型的一类问题之一.如果多线程环境下代码运行的结果是符合我们预期的,即该结果正是在单线程环境中应该出现的结果,则说这个程序是线程安全的. 通俗来说,线程不安全指的就是某一代 ...

  3. 一文教会你什么线程安全以及如何实现线程安全

    title: 一文教会你什么线程安全以及如何实现线程安全 tags: 线程安全 Java并发 Java内存模型 synchronized volatile Lock 文章目录 一.线程安全的概念 二. ...

  4. 线程及同步的性能 – 线程池/ ThreadPoolExecutors/ ForkJoinPool

    线程池和ThreadPoolExecutors 虽然在程序中可以直接使用Thread类型来进行线程操作,但是更多的情况是使用线程池,尤其是在Java EE应用服务器中,一般会使用若干个线程池来处理来自 ...

  5. 【Android 异步操作】线程池 ( 线程池 reject 拒绝任务 | 线程池 addWorker 添加任务 )

    文章目录 一.线程池 reject 拒绝任务 二.线程池 addWorker 添加任务 在上一篇博客 [Android 异步操作]线程池 ( 线程池 execute 方法源码解析 ) 中 , 讲解 线 ...

  6. java——自己实现基础的线程池及带有任务数过多拒绝策略、线程池销毁、自动扩充线程数量及闲时自动回收线程等操作的改进版线程池

    1. 实现第一版基础的线程池 1.1 首先我们定义一个线程池类ThreadPool,然后线程池有一个容器存放我们创建的线程,另一个容器则是存放当前线程池需要处理的任务队列,线程容器用ArrayList ...

  7. java 停止一个线程_Java如何停止一个线程

    线程正常执行完毕,正常结束. 2.监视某些条件,直到某些条件成立,结束线程. class TestMyThread extends Thread { private volatile boolean ...

  8. C#中的多线程-线程同步基础 (控制线程数量)

    同步要领 下面的表格列展了.NET对协调或同步线程动作的可用的工具: 简易阻止方法 构成 目的 Sleep 阻止给定的时间周期 Join 等待另一个线程完成 锁系统 构成 目的 跨进程? 速度 loc ...

  9. hashmap为什么线程不安全_什么时候线程不安全?怎样做到线程安全?怎么扩展线程安全的类?...

    本文同名博客老炮说Java:https://www.laopaojava.com/,每天更新Spring/SpringMvc/SpringBoot/实战项目等文章资料 顺便再给大家推荐一套Spring ...

最新文章

  1. 1.3 Integer类详解
  2. Golang map输出排序
  3. Pwn环境配置(一)——安装虚拟机
  4. java调度:(六)quarts_cron表达式
  5. 如何在liferay ,struts2中跳转页面
  6. Java笔记-Spring Boot JDBC连接Oracle数据库
  7. Spark on Yarn遇到的几个问题
  8. java socket 客户端接收_java socket,怎么把客户端接收到的用户名和密码发送给后台?...
  9. java虚拟机家族种类
  10. 杰控连接mysql_杰控FameView在数据库连接和查询方面的应用———FameView组态软件在数据库处理方面的...
  11. eda交通灯控制器波形输入_EDA交通灯课程设计十字路口交通灯控制器设计.doc
  12. paypal android sdk,Android Paypal SDK错误:商家不接受此类付款
  13. 节点name在graph中无法展示_小节点 · 大奥秘│这正是你想学习的精妙休闲观景空间!(内含视频讲解)...
  14. scrapy 中 COOKIES_ENABLED 设置
  15. JS:dataTables实现跳转首页与尾页功能
  16. 0102Linux基础命令
  17. (详细易懂)一篇文章让你读懂到底什么是Ajax
  18. 洛谷_3975 [TJOI2015]弦论(后缀自动机)
  19. Linux驱动开发学习笔记【8】:Linux中断系统
  20. 《只是为了好玩:Linux之父林纳斯自传》读后感

热门文章

  1. SAP已发票校验采购订单退货 - 特殊业务
  2. WDA将改变现有的abap的开发方式
  3. ABAP 获取登陆者的IP地址和主机名
  4. oracle用dba登陆怎么登,以SQLDBA身份登录isqlplus
  5. redmine备份_Redmine 数据迁移记录
  6. oracle 快速上手,Oracle学习笔记:快速上手
  7. java 8 语法糖_Java8的lamada算是一种语法糖吗?
  8. java commons.util_Java — CommonUtil
  9. python保存创建文件报错 with open(fileName,‘w‘) as fp: IOError: [Errno 22] invalid mode (‘w‘) or filename
  10. 19道Python基础列表元祖的练习题