volatile和synchronized的区别

volatile和synchronized特点

首先需要理解线程安全的两个方面:执行控制内存可见

执行控制的目的是控制代码执行(顺序)及是否可以并发执行。

内存可见控制的是线程执行结果在内存中对其它线程的可见性。根据Java内存模型的实现,线程在具体执行时,会先拷贝主存数据到线程本地(CPU缓存),操作完成后再把结果从线程本地刷到主存。

synchronized关键字解决的是执行控制的问题,它会阻止其它线程获取当前对象的监控锁,这样就使得当前对象中被synchronized关键字保护的代码块无法被其它线程访问,也就无法并发执行。更重要的是,synchronized还会创建一个内存屏障,内存屏障指令保证了所有CPU操作结果都会直接刷到主存中,从而保证了操作的内存可见性,同时也使得先获得这个锁的线程的所有操作,都happens-before于随后获得这个锁的线程的操作。

volatile关键字解决的是内存可见性的问题,会使得所有对volatile变量的读写都会直接刷到主存,即保证了变量的可见性。这样就能满足一些对变量可见性有要求而对读取顺序没有要求的需求。

使用volatile关键字仅能实现对原始变量(如boolen、 short 、int 、long等)操作的原子性,但需要特别注意, volatile不能保证复合操作的原子性,即使只是i++,实际上也是由多个原子操作组成:read i; inc; write i,假如多个线程同时执行i++volatile只能保证他们操作的i是同一块内存,但依然可能出现写入脏数据的情况。

在Java 5提供了原子数据类型atomic wrapper classes,对它们的increase之类的操作都是原子操作,不需要使用sychronized关键字。

对于volatile关键字,当且仅当满足以下所有条件时可使用:

1. 对变量的写入操作不依赖变量的当前值,或者你能确保只有单个线程更新变量的值。
2. 该变量没有包含在具有其他变量的不变式中。

volatile和synchronized的区别

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

如果想更好地理解这两个关键字的作用,强烈建议看一下这篇文章:Java内存模型

时间: 2024-11-01 14:48:12

volatile和synchronized的区别的相关文章

volatile和synchronized的区别和联系

1,volatile    它所修饰的变量不保留拷贝,直接访问主内存中的.    在Java内存模型中,有main memory,每个线程也有自己的memory (例如寄存器).为了性能,一个线程会在自己的memory中保持要访问的变量的副本.这样就会出现同一个变 量在某个瞬间,在一个线程的memory中的值可能与另外一个线程memory中的值,或者main memory中的值不一致的情况. 一个变量声明为volatile,就意味着这个变量是随时会被其他线程修改的,因此不能将它cache在线程m

java多线程中的volatile和synchronized用法分析_java

本文实例分析了java多线程中的volatile和synchronized用法.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: package com.chzhao; public class Volatiletest extends Thread {     private static int count = 0;     public void run() {         count++;     }     public static void main(String

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

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

多线程之:lock和synchronized的区别

多次思考过这个问题,都没有形成理论,今天有时间了,我把他总结出来,希望对大家有所帮助     1.ReentrantLock 拥有Synchronized相同的并发性和内存语义,此外还多了 锁投票,定时锁等候和中断锁等候      线程A和B都要获取对象O的锁定,假设A获取了对象O锁,B将等待A释放对O的锁定,      如果使用 synchronized ,如果A不释放,B将一直等下去,不能被中断      如果 使用ReentrantLock,如果A不释放,可以使B在等待了足够长的时间以后,

全面理解Java内存模型

Java内存模型即Java Memory Model,简称JMM.JMM定义了Java 虚拟机(JVM)在计算机内存(RAM)中的工作方式.JVM是整个计算机虚拟模型,所以JMM是隶属于JVM的. 如果我们要想深入了解Java并发编程,就要先理解好Java内存模型.Java内存模型定义了多线程之间共享变量的可见性以及如何在需要的时候对共享变量进行同步.原始的Java内存模型效率并不是很理想,因此Java1.5版本对其进行了重构,现在的Java8仍沿用了Java1.5的版本. 关于并发编程 在并发

《Java多线程编程核心技术》——第2章对象及变量的并发访问

第2章对象及变量的并发访问本章主要介绍Java多线程中的同步,也就是如何在Java语言中写出线程安全的程序,如何在Java语言中解决非线程安全的相关问题.多线程中的同步问题是学习多线程的重中之重,这个技术在其他的编程语言中也涉及,如C++或C#.本章应该着重掌握如下技术点:synchronized对象监视器为Object时的使用.synchronized对象监视器为Class时的使用.非线程安全是如何出现的.关键字volatile的主要作用.关键字volatile与synchronized的区别

Java线程机制(三) synchronized和volatile的使用

现在开始进入线程编程中最重要的话题---数据同步,它是线程编程的核心,也是难点,就算我们理解了 数据同步的基本原理,但是我们也无法保证能够写出正确的同步代码,但基本原理是必须掌握的. 要 想理解数据同步的基本原理,首先就要明白,为什么我们要数据同步? public class CharacterDisplayCanvas extends JComponent implements CharacterListener { protected FontMetrics fm; protected ch

Java多线程基础总结三: volatile

前面的两篇总结简单的说明了同步的一些问题,在使用基础的同步机制中还有两个可以分享的技术:volatile关键字和ThreadLocal.合 理的根据场景利用这些技术,可以有效的提高并发的性能,下面尝试结合自己的理解叙述这部分的内容,应该会有理解的偏差,我也会尽量 的在完善自己理解的同时同步更新文章的错误. 或许在知道synchronized配和对象内部锁的机制以后,可以提高写出正确同步的并发程序成功率,但是这时候会遇到另一个大问题:性 能!是的,对于 synchronized带来的可能庞大的性能

volatile限定符{C}

PS: ...Newbie love coding-  Linux_c一站式编程(volatile限定符介绍) linux_c的volatile限定符 现在探讨一下编译器优化会对生成的指令产生什么影响,在此基础上介绍C语言的volatile限定符.看下面的例子: 我们用recv和send这两个全局变量来模拟设备寄存器.假设某种平台采用内存映射I/O,串口发送寄存器和串口接收寄存器位于固定的内存地址,而recv和send这两个全局变量也有固定的内存地址,所以在这个例子中把它们假想成串口接收寄存器和