volatile是一个变量修饰符,而synchronized是一个方法或块的修饰符。所以我们使用这两种关键字来指定三种简单的存取变量的方式。

int i1;                       int geti1() {return i1;}

volatile int i2;                       int geti2() {return i2;}

int i3;          synchronized int geti3() {return i3;}

geti1()在当前线程中立即获取在i1变量中的值。线程可以获得变量的本地拷贝,而所获得的变量的值并不一定与其他线程所获得的值相同。特别是,如果其他的线程修改了i1的值,那么当前线程获得的i1的值可能与修改后的值有所差别。实际上,Java有一种主内存的机制,使用一个主内存来保存变量当前的正确的值。线程将变量的值拷贝到自己独立的内存中,而这些线程的内存拷贝可能与主内存中的值不同。所以实际当中可能发生这样的情况,在主内存中i1的值为1,线程1和线程2都更改了i1,但是却没把更新的值传回给主内存或其他线程中,那么可能在线程1中i1的值为2,线程2中i1的值却为3。

另一方面,geti2()可以有效的从主内存中获取i2的值。一个volatile类型的变量不允许线程从主内存中将变量的值拷贝到自己的存储空间。因此,一个声明为volatile类型的变量将在所有的线程中同步的获得数据,不论你在任何线程中更改了变量,其他的线程将立即得到同样的结果。由于线程存取或更改自己的数据拷贝有更高的效率,所以volatile类型变量在性能上有所消耗。

那么如果volatile变量已经可以使数据在线程间同步,那么synchronizes用来干什么呢?两者有两方面的不同。首先,synchronized获取和释放由监听器控制的锁,如果两个线程都使用一个监听器(即相同对象锁),那么监听器可以强制在一个时刻只有一个线程能处理代码块,这是最一般的同步。另外,synchronized还能使内存同步。在实际当中,synchronized使得所有的线程内存与主内存相同步。所以geti3()的执行过程如下:

1.   线程从监听器获取对象的锁。(这里假设监听器非锁,否则线程只有等到监听器解锁才能获取对象锁)

2.   线程内存更新所有的变量,也就是说他将读取主内存中的变量使自己的变量保证有效。(JVM会使用一个“脏”标志来最优化过程,使得仅仅具有“脏”标志变量被更新。详细的情况查询JAVA规范的17.9)

3.   代码块被执行(在这个例子中,设置返回值为刚刚从主内存重置的i3当前的值。)

4.   任何变量的变更将被写回到主内存中。但是这个例子中geti3()没有什么变化。

5.   线程释放对象的锁给监听器。

所以volatile只能在线程内存和主内存之间同步一个变量的值,而synchronized则同步在线程内存和主内存之间的所有变量的值,并且通过锁住和释放监听器来实现。显然,synchronized在性能上将比volatile更加有所消耗。

=============关于两者的区别===================

1.volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取;synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
2.volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的
3.volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性
4.volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。
5.volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化

红字体部分的原因如下:
线程A修改了变量还没结束时,另外的线程B可以看到已修改的值,而且可以修改这个变量,而不用等待A释放锁,因为Volatile 变量没上锁

volatile和synchronized的区别与联系[转]的更多相关文章

  1. volatile和synchronized的区别

    volatile和synchronized特点 首先需要理解线程安全的两个方面:执行控制和内存可见. 执行控制的目的是控制代码执行(顺序)及是否可以并发执行. 内存可见控制的是线程执行结果在内存中对其 ...

  2. 多线程学习:Volatile与Synchronized的区别、什么是重排序

    java线程的内存模型 java的线程内存模型中定义了每个线程都有一份自己的共享变量副本(本地内存),里面存放自己私有的数据,其他线程不能直接访问,而一些共享变量则存在主内存中,供所有线程访问. 上图 ...

  3. 多线程的指令重排问题:as-if-serial语义,happens-before语义;volatile关键字,volatile和synchronized的区别

    一.指令重排问题 你写的代码有可能,根本没有按照你期望的顺序执行,因为编译器和 CPU 会尝试指令重排来让代码运行更高效,这就是指令重排. 1.1 虚拟机层面 我们都知道CPU执行指令的时候,访问内存 ...

  4. Volatile关键字&&DCL单例模式,volatile 和 synchronized 的区别

    Volatile 英文翻译:易变的.可变的.不稳定的. 一.volatile 定义及用法 多个线程的工作内存彼此独立,互不可见,线程启动的时候,虚拟机为每个内存分配一块工作内存,不仅包含了线程内部定义 ...

  5. 【转】volatile和synchronized的区别

    volatile和synchronized的区别 volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取: synchronized则是锁定当前变量,只有当前 ...

  6. volatile与synchronized的区别

    1.锁提供了两种主要特性:互斥(mutual exclusion) 和可见性(visibility). 互斥即一次只允许一个线程持有某个特定的锁,因此可使用该特性实现对共享数据的协调访问协议,这样,一 ...

  7. java多线程中 volatile与synchronized的区别-阿里面试

    volatile 与 synchronized 的比较(阿里面试官问的问题) ①volatile轻量级,只能修饰变量.synchronized重量级,还可修饰方法 ②volatile只能保证数据的可见 ...

  8. volatile和synchronized的区别和联系

    volatile 它所修饰的变量不保留拷贝,直接访问主内存中的.   在Java内存模型中,有main memory,每个线程也有自己的memory (例如寄存器).为了性能,一个线程会在自己的mem ...

  9. Java中的Volatile和synchronized的区别

    Synchronized和Volatile四个不同点: 1.粒度不同,前者锁对象和类 ,后者针对变量2.syn阻塞,volatile线程不阻塞3.syn保证三大特性,volatile不保证原子性4.s ...

随机推荐

  1. UIKit框架之NSObject

    首先学习NSObject // // ViewController.m // localization // // Created by City--Online on 15/5/15. // Cop ...

  2. Java虚拟机 - 类加载机制

    [深入Java虚拟机]之四:类加载机制 类加载过程     类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载.验证.准备.解析.初始化.使用和卸载七个阶段.它们开始的顺序如下 ...

  3. SqlSession对象之StatementHandler

    上一篇讲了SqlSession对象中的Executor,接下来将对SqlSession的另一个对象StatementHandler进行讲解. 一.StatementHandler介绍 Statemen ...

  4. 设计模式-生成器(Builder)

     一.概念 将一个复杂对像的构建与它的表示分离,使得同样的构建过程创建不同的表示,又叫建造模式. 生成器模式的重心在于分离构建算法和具体的构造实现,从而使得构建算法可以重用.采用不同的构建实现,产生不 ...

  5. css3 flex弹性盒子布局梳理,打通任督二脉

    挺早就接触了css的flex布局,深入使用也就是在近期移动端开发.老来多健忘,只能自己梳理一下知识点,当做温故知新吧. ,请原谅小白的才疏学浅,写的不到位的地方请指正. flex属性用于设置或检索弹性 ...

  6. Impala随手记

    最近开始使用Impala,基本完全兼容传统SQL,并且查询速度飞快,是Hive的良好替代: 1.登录及简单查询 impala-shell #列出数据库 show databases; #载入数据库 u ...

  7. Docker相关概念

    一.概念 ①云计算:是一种资源的服务模式,该模式可以实现随时随地,便捷按需地从可配置计算资源共享池中获取所需的资源(如网络.服务器.存储.应用及服务),资源能够快速供应并释放,大大减少了资源管理工作的 ...

  8. Python 数据分析基础小结

    一.数据读取 1.读写数据库数据 读取函数: pandas.read_sql_table(table_name, con, schema=None, index_col=None, coerce_fl ...

  9. leetCode题解之Longest Palindrome

    1.题目描述 2.问题分析 直接用hash table 做就行. 3.代码 int longestPalindrome(string s) { ) ; map<char,int> m; f ...

  10. EmEditor的一个好用的正则替换功能

    最近在编辑文本的时候用到了EmEditor的一个好用的正则替换功能.即我想用搜索到内容的一部分来生成另一段文本.例如客户提供给我一大堆MYSQL的建立主键的脚本,我想改成MSSQL的建立主键的脚本,这 ...