volatile和synchronized 差别

1、什么是volatile

Volatile修饰的成员变量在每次被线程訪问时,都强迫从共享内存中重读该成员变量的值。并且,当成员变量发生变化时,强迫线程将变化值回写到共享内存。这样在不论什么时刻,两个不同的线程总是看到某个成员变量的同一个值。

Java语言规范中指出:为了获得最佳速度。同意线程保存共享成员变量的私有拷贝。并且仅仅当线程进入或者离开同步代码块时才与共享成员变量的原始值对照。这样当多个线程同一时候与某个对象交互时,就必需要注意到要让线程及时的得到共享成员变量的变化。

而volatilekeyword就是提示VM:对于这个成员变量不能保存它的私有拷贝,而应直接与共享成员变量交互。

使用建议:在两个或者很多其它的线程訪问的成员变量上使用volatile。

当要訪问的变量已在synchronized代码块中。或者为常量时。不必使用。

因为使用volatile屏蔽掉了VM中必要的代码优化,所以在效率上比較低。因此一定在必要时才使用此keyword。

2、volatile和synchronized 差别

  1. volatile本质是在告诉jvm当前变量在寄存器中的值是不确定的,须要从主存中读取,synchronized则是锁定当前变量,仅仅有当前线程能够訪问该变量,其它线程被堵塞住.
  2. volatile仅能使用在变量级别,synchronized则能够使用在变量,方法.
  3. volatile仅能实现变量的改动可见性,但不具备原子特性,而synchronized则能够保证变量的改动可见性和原子性.
  4. volatile不会造成线程的堵塞,而synchronized可能会造成线程的堵塞.
  5. volatile标记的变量不会被编译器优化,而synchronized标记的变量能够被编译器优化.

引用:

http://blog.csdn.net/majorboy/article/details/475811

这个可能是最好的对照volatile和synchronized作用的文章了。

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

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更加有所消耗。

时间: 2024-11-07 20:59:55

volatile和synchronized 差别的相关文章

关于volatile和synchronized

这个可能是最好的对比volatile和synchronized作用的文章了.volatile是一个变量修饰符,而synchronized是一个方法或块的修饰符.所以我们使用这两种关键字来指定三种简单的存取变量的方式. int i1;                       int geti1() {return i1;} volatile int i2;                       int geti2() {return i2;} int i3;          synch

java学习:JMM(java memory model)、volatile、synchronized、AtomicXXX理解

一.JMM(java memory model)内存模型 从网上淘来二张图: 上面这张图说的是,在多核CPU的系统中,每个核CPU自带高速缓存,然后计算机主板上也有一块内存-称为主内(即:内存条).工作时,CPU的高速缓存中的数据通过一系列手段来保证与主内的数据一致(CacheCoherence),更直白点,高速缓存要从主内中load数据,处理完以后,还要save回主存. 上图说的是,java中的各种变量(variable)保存在主存中,然后每个线程自己也有自己的工作内存区(working me

volatile 与 synchronized 区别

在Java中,为了保证多线程读写数据时保证数据的一致性,可以采用两种方式: 同步 如用synchronized关键字,或者使用锁对象. volatile 使用volatile关键字用一句话概括volatile,它能够使变量在值发生改变时能尽快地让其他线程知道. volatile详解 首先我们要先意识到有这样的现象,编译器为了加快程序运行的速度,对一些变量的写操作会先在寄存器或者是CPU缓存上进行,最后才写入内存.而在这个过程,变量的新值对其他线程是不可见的.而volatile的作用就是使它修饰的

volatile与synchronized的区别

1.锁提供了两种主要特性:互斥(mutual exclusion) 和可见性(visibility). 互斥即一次只允许一个线程持有某个特定的锁,因此可使用该特性实现对共享数据的协调访问协议,这样,一次就只有一个线程能够使用该共享数据. 可见性要更加复杂一些,它必须确保释放锁之前对共享数据做出的更改对于随后获得该锁的另一个线程是可见的 —— 如果没有同步机制提供的这种可见性保证,线程看到的共享         变量可能是修改前的值或不一致的值,这将引发许多严重问题.(竞态条件) 2.在Java中

JAVA多线程之volatile 与 synchronized 的比较

一,volatile关键字的可见性 要想理解volatile关键字,得先了解下JAVA的内存模型,Java内存模型的抽象示意图如下: 从图中可以看出: ①每个线程都有一个自己的本地内存空间--线程栈空间???线程执行时,先把变量从主内存读取到线程自己的本地内存空间,然后再对该变量进行操作 ②对该变量操作完后,在某个时间再把变量刷新回主内存 关于JAVA内存模型,更详细的可参考: 深入理解Java内存模型(一)——基础 因此,就存在内存可见性问题,看一个示例程序:(摘自书上) 1 public c

并发编程之ThreadLocal、Volatile、synchronized、Atomic关键字扫盲

前言 对于ThreadLocal.Volatile.synchronized.Atomic这四个关键字,我想一提及到大家肯定都想到的是解决在多线程并发环境下资源的共享问题,但是要细说每一个的特点.区别.应用场景.内部实现等,却可能模糊不清,说不出个所以然来,所以,本文就对这几个关键字做一些作用.特点.实现上的讲解. 1.Atomic 作用 对于原子操作类,Java的concurrent并发包中主要为我们提供了这么几个常用的:AtomicInteger.AtomicLong.AtomicBoole

ThreadLocal、Volatile、synchronized、Atomic

前言 对于ThreadLocal.Volatile.synchronized.Atomic这四个关键字,我想一提及到大家肯定都想到的是解决在多线程并发环境下资源的共享问题,但是要细说每一个的特点.区别.应用场景.内部实现等,却可能模糊不清,说不出个所以然来,所以,本文就对这几个关键字做一些作用.特点.实现上的讲解. 1.Atomic 作用 对于原子操作类,Java的concurrent并发包中主要为我们提供了这么几个常用的:AtomicInteger.AtomicLong.AtomicBoole

从JAVA看C#中volatile和synchronized关键字的作用

最近一直在想C#中 volatile关键字到底是用来干什么的?查了很多.NET的文章都是说用volatile修饰的变量可以让多线程同时修改,这是什么鬼... 然后查到了下面这篇JAVA中关于volatile和synchronized关键字的概述,总算对volatile和synchronized关键字有了个大概的了解,而C#中应该类似,注意C#中没有synchronized关键字,但是有MethodImplAttribute 类 和 SynchronizationAttribute 类与JAVA中

Thread 学习记录 <1> -- volatile和synchronized

恐怕比较一下volatile和synchronized的不同是最容易解释清楚的.volatile是变量修饰符,而synchronized则作用于一段代码或方法:看如下三句get代码: int i1;              int geti1() {return i1;} volatile int i2;  int geti2() {return i2;} int i3;              synchronized int geti3() {return i3;} geti1()得到存