转载:http://blog.csdn.net/guyuealian/article/details/52525724

在说明Java多线程内存可见性之前,先来简单了解一下Java内存模型。
     (1)Java所有变量都存储在主内存中
     (2)每个线程都有自己独立的工作内存,里面保存该线程的使用到的变量副本(该副本就是主内存中该变量的一份拷贝)
   (1)线程对共享变量的所有操作都必须在自己的工作内存中进行,不能直接在主内存中读写
   (2)不同线程之间无法直接访问其他线程工作内存中的变量,线程间变量值的传递需要通过主内存来完成。
线程1对共享变量的修改,要想被线程2及时看到,必须经过如下2个过程:
   (1)把工作内存1中更新过的共享变量刷新到主内存中
   (2)将主内存中最新的共享变量的值更新到工作内存2中
可见性与原子性
   可见性:一个线程对共享变量的修改,更够及时的被其他线程看到
   原子性:即不可再分了,不能分为多步操作。比如赋值或者return。比如"a = 1;"和 "return a;"这样的操作都具有原子性。类似"a += b"这样的操作不具有原子性,在某些JVM中"a += b"可能要经过这样三个步骤:
① 取出a和b
② 计算a+b
③ 将计算结果写入内存
 
(1)Synchronized:保证可见性和原子性
    Synchronized能够实现原子性和可见性;在Java内存模型中,synchronized规定,线程在加锁时,先清空工作内存→在主内存中拷贝最新变量的副本到工作内存→执行完代码→将更改后的共享变量的值刷新到主内存中→释放互斥锁。

(2)Volatile:保证可见性,但不保证操作的原子性
    Volatile实现内存可见性是通过store和load指令完成的;也就是对volatile变量执行写操作时,会在写操作后加入一条store指令,即强迫线程将最新的值刷新到主内存中;而在读操作时,会加入一条load指令,即强迫从主内存中读入变量的值。但volatile不保证volatile变量的原子性,例如:

  1. Private int Num=0;
  2. Num++;//Num不是原子操作

Num不是原子操作,因为其可以分为:读取Num的值,将Num的值+1,写入最新的Num的值。
    对于Num++;操作,线程1和线程2都执行一次,最后输出Num的值可能是:1或者2
   【解释】输出结果1的解释:当线程1执行Num++;语句时,先是读入Num的值为0,倘若此时让出CPU执行权,线程获得执行,线程2会重新从主内存中,读入Num的值还是0,然后线程2执行+1操作,最后把Num=1刷新到主内存中; 线程2执行完后,线程1由开始执行,但之前已经读取的Num的值0,所以它还是在0的基础上执行+1操作,也就是还是等于1,并刷新到主内存中。所以最终的结果是1

    一般在多线程中使用volatile变量,为了安全,对变量的写入操作不能依赖当前变量的值:如Num++或者Num=Num*5这些操作。

(3)Synchronized和Volatile的比较
    1)Synchronized保证内存可见性和操作的原子性
    2)Volatile只能保证内存可见性
    3)Volatile不需要加锁,比Synchronized更轻量级,并不会阻塞线程(volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。)
    4)volatile标记的变量不会被编译器优化,而synchronized标记的变量可以被编译器优化(如编译器重排序的优化).
    5)volatile是变量修饰符,仅能用于变量,而synchronized是一个方法或块的修饰符。
      volatile本质是在告诉JVM当前变量在寄存器中的值是不确定的,使用前,需要先从主存中读取,因此可以实现可见性。而对n=n+1,n++等操作时,volatile关键字将失效,不能起到像synchronized一样的线程同步(原子性)的效果。

java并发之可见性与原子性:Syncronized和volatile的更多相关文章

  1. Java多线程之可见性与原子性——synchronized VS volatile

    <转:http://blog.csdn.net/uniquewonderq/article/details/48113071> 程序举例: 代码: package com.synch; p ...

  2. 【慕课网学习笔记】Java共享变量的可见性和原子性

    1. Java内存模型(Java Memory Model, JMM) Java的内存模型如下,所有变量都存储在主内存中,每个线程都有自己的工作内存. 共享变量:如果一个变量在多个线程中都使用到了,那 ...

  3. Java-JUC(二):Java内存模型可见性、原子性、有序性及volatile具有特性

    1.Java HotSpot JVM运行时数据区 Java内存模型即Java Memory Model,简称JMM.JMM定义了Java 虚拟机(JVM)在计算机内存(RAM)中的工作方式.JVM是整 ...

  4. 【转】可见性、原子性和有序性问题:并发编程Bug的源头

    如果你细心观察的话,你会发现,不管是哪一门编程语言,并发类的知识都是在高级篇里.换句话说,这块知识点其实对于程序员来说,是比较进阶的知识.我自己这么多年学习过来,也确实觉得并发是比较难的,因为它会涉及 ...

  5. Java 并发之原子性与可见性

    原子性 原子是世界上的最小单位,具有不可分割性.比如 a=0:(a非long和double类型) 这个操作是不可分割的,那么我们说这个操作时原子操作.再比如:a++: 这个操作实际是a = a + 1 ...

  6. Java多线程之内存可见性和原子性:Synchronized和Volatile的比较

    Java多线程之内存可见性和原子性:Synchronized和Volatile的比较     [尊重原创,转载请注明出处]http://blog.csdn.net/guyuealian/article ...

  7. Java三大性质总结:原子性、可见性以及有序性

    本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...

  8. Java多线程中提到的原子性和可见性、有序性

    1.原子性(Atomicity)   原子性是指在一个操作中就是cpu不可以在中途暂停然后再调度,既不被中断操作,要不执行完成,要不就不执行. 如果一个操作时原子性的,那么多线程并发的情况下,就不会出 ...

  9. 【漫画】JAVA并发编程三大Bug源头(可见性、原子性、有序性)

    原创声明:本文转载自公众号[胖滚猪学编程]​ 某日,胖滚猪写的代码导致了一个生产bug,奋战到凌晨三点依旧没有解决问题.胖滚熊一看,只用了一个volatile就解决了.并告知胖滚猪,这是并发编程导致的 ...

随机推荐

  1. UNIX网络编程——客户/服务器程序设计示范(一)

    下面给出的是客户程序用于测试我们的服务器程序的各个变体. #include "unp.h" #define MAXN 16384 /* max # bytes to request ...

  2. Hessian探究(一)Hessian入门示例

    一.hessian的maven信息: [html] view plain copy print? <dependency> <groupId>com.caucho</gr ...

  3. MyEclipse2014搭建JSF项目实例

    开发环境:  Windows2008 R2 64位 + MyEclipse Professional 2014 +JDK1.7+Tomcat7.0 搭建步骤: 1.打开MyEclipse2014后新建 ...

  4. Salt: Master server cannot see any Minion

    Issue: When you set up a Salt Master server and several Minions, you may find that none of minions c ...

  5. Android进阶(二十八)上下文菜单ContextMenu使用案例

    上下文菜单ContextMenu使用案例 前言 回顾之前的应用程序,发现之前创建的选项菜单无法显示了.按照正常逻辑来说,左图中在"商品信息"一栏中应该存在选项菜单,用户可进行分享等 ...

  6. 【TCP/IP 协议】 TCP/IP 基础

    总结 : 通过学习 TCP/IP 基础, 并总结相关笔记 和 绘制思维导图 到博客上, 对 TCP/IP 框架有了大致了解, 之后开始详细学习数据链路层的各种细节协议, 并作出笔记; 博客地址 : h ...

  7. Android进阶(九)APP编程感想

    从初识Android到现在,在不断做APP(二维码.条形码扫描,彩票购买,火车票余票查询)的过程中,自己学会了很多东西.找时间整理了一下,总结如下: 其中,对于前两个APP,自己都是在他人已完成的基础 ...

  8. Java Web 高性能开发,第 1 部分: 前端的高性能

    Web 发展的速度让许多人叹为观止,层出不穷的组件.技术,只需要合理的组合.恰当的设置,就可以让 Web 程序性能不断飞跃.所有 Web 的思想都是通用的,它们也可以运用到 Java Web.这一系列 ...

  9. 工作中常用的Linux命令

    1.从其他机器拷贝文件夹 格式: scp -r 文件夹名 用户名@机器名:/路径 范例: scp -rsearch work@zjm-testing-ps23.zjm.baidu.com:/home/ ...

  10. UILabel-UITextField-UIBotton&nbsp;UI_…

    注意:AppDelegate是类,所以self在这个类中指的就是AppDelegate对象 - (BOOL)application:(UIApplication *)application didFi ...