synchronized和volatile简介
简介
volatile是一个变量修饰符,而synchronized是一个方法或块的修饰符。所以我们使用这两种关键字来指定三种简单的存取变量的方式。
1 |
int i1; |
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()的执行过程如下:
- 线程从监听器获取对象的锁。(这里假设监听器非锁,否则线程只有等到监听器解锁才能获取对象锁)
- 线程内存更新所有的变量,也就是说他将读取主内存中的变量使自己的变量保证有效。(JVM会使用一个“脏”标志来最优化过程,使得仅仅具有“脏”标志变量被更新。详细的情况查询JAVA规范的17.9)
- 代码块被执行(在这个例子中,设置返回值为刚刚从主内存重置的i3当前的值。)
- 任何变量的变更将被写回到主内存中。但是这个例子中geti3()没有什么变化。
- 线程释放对象的锁给监听器。
所以volatile只能在线程内存和主内存之间同步一个变量的值,而synchronized则同步在线程内存和主内存之间的所有变量的值,并且通过锁住和释放监听器来实现。显然,synchronized在性能上将比volatile更加有所消耗。
关于两者的区别
- volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取;synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。
- volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的
- volatile仅能实现变量的修改可见性,不能保证原子性;而synchronized则可以保证变量的修改可见性和原子性
- volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。
- volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化
参考
synchronized和volatile简介的更多相关文章
- volatile简介
volatile简介 java语言提供了一种稍弱的内存同步机制,即volatile变量.用来确保将变量的更新操作通知到其它线程,保证了新值能立即同步到主内存,以及每次使用前立即从内存刷新.当变量声明为 ...
- Java 线程 — synchronized、volatile、锁
线程同步基础 synchronized 和volatile是Java线程同步的基础. synchronized 将临界区的内容上锁,同一时刻只有一个进程能访问该临界区代码 使用的是内置锁,锁一个时刻只 ...
- synchronized和volatile的使用
synchronized和volatile的使用 一步一步掌握线程机制(三)---synchronized和volatile的使用 现在开始进入线程编程中最重要的话题---数据同步,它是线程编程的核心 ...
- java多线程系列(五)---synchronized ReentrantLock volatile Atomic 原理分析
java多线程系列(五)---synchronized ReentrantLock volatile Atomic 原理分析 前言:如有不正确的地方,还望指正. 目录 认识cpu.核心与线程 java ...
- java多线程之内存可见性-synchronized、volatile
1.JMM:Java Memory Model(Java内存模型) 关于synchronized的两条规定: 1.线程解锁前,必须把共享变量的最新值刷新到主内存中 2.线程加锁时,将清空工作内存中共享 ...
- synchronized和volatile比较
synchronized和volatile比较 volatile不需要加锁,比synchronized更轻量级,不会阻塞线程 从内存可见性角度讲,volatile读相当于加锁,volatile写相当于 ...
- java并发编程(2) --Synchronized与Volatile区别
Synchronized 在多线程并发中synchronized一直是元老级别的角色.利用synchronized来实现同步具体有一下三种表现形式: 对于普通的同步方法,锁是当前实例对象. 对于静态同 ...
- synchronized与volatile的区别及各自的作用、原理(学习记录)
synchronized与volatile的区别,它们的作用及原理? 说到两者的区别,先要了解锁提供的两种特性:互斥(mutual exclusion) 和可见性(visibility). 互斥:即一 ...
- synchronized和lock以及synchronized和volatile的区别
synchronized和volatile区别synochronizd和volatile关键字区别: 1. volatile关键字解决的是变量在多个线程之间的可见性:而sychronized关键字解决 ...
随机推荐
- matlab GUI保存axes(坐标轴)上的图像
1.默认方式 matlab GUI默认菜单的保存图像默认为保持全部GUI,包括使用" 菜单->编辑->复制图形". 2 保存可见区域 2.1 代码 [FileName, ...
- sxoi爆炸祭
好吧,纯粹是去玩玩的,我这么一个弱省的蒟蒻,进队纯粹是开玩笑.... Day0 去五中试机,感觉电脑手感不错,打了半个线段树的板子才发现试机要在自己的电脑上试,然后我无奈的搬东西(从26号搬到2号), ...
- SNMP相关的RFC建议和链接
1. SNMP Books or Articleshttp://www.faqs.org/faqs/snmp-faq/part1/http://www.faqs.org/faqs/snmp-faq/p ...
- sso系统使用
一:什么是sso(single sign on) ? sso(单点登录系统)简单说就是客户端第一次访问应用1的时候,由于没有登录,会被引导到登录页面进行登录,如果登录校验通过,将返回一个认证信息tic ...
- CSS3实现多样的边框效果
半透明边框 实现效果: 实现代码: <div> 你能看到半透明的边框吗? </div> div { /* 关键代码 */ border: 10px solid rgba(255 ...
- 经典的java中return和finally问题!
经典的java中return和finally问题! 标签: 杂谈 分类: java学习 前一段时间 参加公司的笔试问了这个问题,回来一查才知道当时自己做错了,百思不得其解,上网查到下面的程序,但是运行 ...
- 第四章:4.2MySQL 权限系统介绍
4.2.1 权限系统简介 MySQL 的权限系统在实现上比较简单,相关权限信息主要存储在几个被称为granttables 的系统表中,即: mysql.User,mysql.db,mysql.Host ...
- git merge 与 git rebase
git merge git rebase merge V.S. rebase 参考材料 写在开始: 对merge和rebase的用法总有疑惑,好像两个都能完成"获取别的branch的comm ...
- spring cloud 入门系列五:使用Feign 实现声明式服务调用
一.Spring Cloud Feign概念引入通过前面的随笔,我们了解如何通过Spring Cloud ribbon进行负责均衡,如何通过Spring Cloud Hystrix进行服务断路保护,两 ...
- 架构之微服务(etcd)
1. ETCD是什么 ETCD是用于共享配置和服务发现的分布式,一致性的KV存储系统.该项目目前最新稳定版本为2.3.0. 具体信息请参考[项目首页]和[Github].ETCD是CoreOS公司发起 ...