java 语言中允许线程访问共享变量,为了保证共享变量能被准确和一致的更新,Java 语言提供了volatile 关键字,也就是我们所说的内存一致性

问题抛出:(尝试去运行下面代码,以及将volatile 加上的运行结果)

/**
* 问题抛出
* @param args
*/
public class Volatile01 { public /*volatile*/ boolean flag = true; public static void main(String[] args) throws InterruptedException {
Volatile01 v =new Volatile01();
RunV r =new RunV(v);
Thread th =new Thread(r);
th.start(); //在main method to modify flag
Thread.sleep(1000);
v.flag=false;
} } class RunV implements Runnable{
Volatile01 vola ;
RunV(Volatile01 vola){
this.vola=vola;
} @Override
public void run() {
//
while(vola.flag) {} System.err.println("flag 状态转变"); } }

问题的原因是是什么呢?

根据上面的运行结果,在没有volatile 关键字的情况下,运行结果是:线程持续陷入死循环状态,flag 并没有改变;

加上volatile 后 运行结果:flag 状态转变,说明flage 已经被改变了;

请看:http://www.infoq.com/cn/articles/ftf-java-volatile 这篇文章,我大致的说一下:主要跟处理器有关,处理器为了运行的效率,不直接跟内存进行通讯;

它是先将内存的数据先读取到cpu 内部缓存(L1,L2,其他)中,操作完之后不知道什么时候才会将数据重新写到内存来修改内存中存在的值,所以在上面的例子中

在修改了flage =true 后,RunV线程是无法感知到的,依然是cpu 缓存的值;

volatile如何保证可见性呢?

依然看上文的那篇文章;里面由一些图文解释;

volatile保证原子性操作吗?是否能解决数据不一致的问题(尝试多运行如下代码,可以得到都不同的结果)?

/**
* volaile 是否支持原子性操作
* @param args
*/
public class Volatile02 { public volatile int v=0; public static void main(String[] args) throws InterruptedException, ExecutionException {
Volatile02 v =new Volatile02();
RunB r =new RunB(v);
List<Thread> theads =new ArrayList<Thread>();
for(int i=0;i<10;i++) {
theads.add(new Thread(r));
} theads.forEach((t->{
t.start();
})); theads.forEach((t->{
try {
t.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
})); System.out.println(v.v);
} } class RunB implements Runnable{
Volatile02 vola ;
RunB(Volatile02 vola){
this.vola=vola;
} @Override
public void run() {
for(int i=0;i<10000;i++) { vola.v++;
System.out.println(Thread.currentThread().getName());
} } }

运行得知,volatile 尽管保证了内存的可见性,但并不能保证多线程下的原子操作导致数据不一致问题;只能靠synchronized 和lock;

最新文章

  1. html5学习笔记一
  2. 如何获取hibernate代理类代理的实际对象实例?
  3. jquery 获取元素在浏览器中的绝对位置
  4. 使用Spring Data JPA查询时,报result returns more than one elements异常
  5. 数据库操作事务IsolationLevel 枚举
  6. unity3d插件Daikon Forge GUI 中文教程2-基础控件Label的使用
  7. iOS开发Swift篇—(三)字符串和数据类型
  8. Iometer介绍与使用
  9. 03-树3 Tree Traversals Again
  10. VS2012编译出来的程序,在XP上运行,出现“.exe 不是有效的 win32 应用程序” “not a valid win32 application”
  11. ASP.NET自定义控件加载资源WebResource问题
  12. Dropping tests(01分数规划)
  13. Actor模型[转]
  14. 2018-2019-2 《Java程序设计》第8周学习总结
  15. linux的sed命令(一)
  16. python 环境安装和卸载1
  17. [Swift]JSON字符串与字典(Dictionary)、数组(Array)之间的相互转换
  18. 修改element ui 默认样式最好的解释
  19. ELK-elasticsearch-6.3.2插件【head,bigdesk,cerebro[kopf]】安装
  20. 数值分析 最小二乘 matlab

热门文章

  1. shiro(安全框架)
  2. Python 回调函数
  3. shutil 拷贝 / 移动 / 压缩 / 解压缩
  4. 半分钟学会使用markdown基本语法
  5. 使用Java监控工具出现 Can&#39;t attach to the process
  6. Scala map与flatMap
  7. django之 使用py文件操作django项目中的表
  8. Redis梳理
  9. Http的那些事: Content-Type
  10. android toolbar效果2