恐怕比较一下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()得到存储在当前线程中i1的数值。多个线程有多个i1变量拷贝,而且这些i1之间可以互不相同。换句话说,另一个线程可能已经改变了它线程内的i1值,而这个值可以和当前线程中的i1值不相同。事实上,Java有个思想叫“主”内存区域,这里存放了变量目前的“准确值”。每个线程可以有它自己的变量拷贝,而这个变量拷贝值可以和“主”内存区域里存放的不同。因此实际上存在一种可能:“主”内存区域里的i1值是1,线程1里的i1值是2,线程2里的i1值是3——这在线程1和线程2都改变了它们各自的i1值,而且这个改变还没来得及传递给“主”内存区域或其他线程时就会发生。
而geti2()得到的是“主”内存区域的i2数值。用volatile修饰后的变量不允许有不同于“主”内存区域的变量拷贝。换句话说,一个变量经volatile修饰后在所有线程中必须是同步的;任何线程中改变了它的值,所有其他线程立即获取到了相同的值。理所当然的,volatile修饰的变量存取时比一般变量消耗的资源要多一点,因为线程有它自己的变量拷贝更为高效。
既然volatile关键字已经实现了线程间数据同步,又要synchronized干什么呢?呵呵,它们之间有两点不同。首先,synchronized获得并释放监视器——如果两个线程使用了同一个对象锁,监视器能强制保证代码块同时只被一个线程所执行——这是众所周知的事实。但是,synchronized也同步内存:事实上,synchronized在“主”内存区域同步整个线程的内存。因此,执行geti3()方法做了如下几步:
1. 线程请求获得监视this对象的对象锁(假设未被锁,否则线程等待直到锁释放)
2. 线程内存的数据被消除,从“主”内存区域中读入(Java虚拟机能优化此步。。。[后面的不知道怎么表达,汗])
3. 代码块被执行
4. 对于变量的任何改变现在可以安全地写到“主”内存区域中(不过geti3()方法不会改变变量值)
5. 线程释放监视this对象的对象锁
因此volatile只是在线程内存和“主”内存间同步某个变量的值,而synchronized通过锁定和解锁某个监视器同步所有变量的值。显然synchronized要比volatile消耗更多资源。
Thread 学习记录 <1> -- volatile和synchronized的更多相关文章
-
【java并发编程艺术学习】(三)第二章 java并发机制的底层实现原理 学习记录(一) volatile
章节介绍 这一章节主要学习java并发机制的底层实现原理.主要学习volatile.synchronized和原子操作的实现原理.Java中的大部分容器和框架都依赖于此. Java代码 ==经过编译= ...
-
java学习:JMM(java memory model)、volatile、synchronized、AtomicXXX理解
一.JMM(java memory model)内存模型 从网上淘来二张图: 上面这张图说的是,在多核CPU的系统中,每个核CPU自带高速缓存,然后计算机主板上也有一块内存-称为主内(即:内存条).工 ...
-
多线程学习:Volatile与Synchronized的区别、什么是重排序
java线程的内存模型 java的线程内存模型中定义了每个线程都有一份自己的共享变量副本(本地内存),里面存放自己私有的数据,其他线程不能直接访问,而一些共享变量则存在主内存中,供所有线程访问. 上图 ...
-
剑指Offer——线程同步volatile与synchronized详解
(转)Java面试--线程同步volatile与synchronized详解 0. 前言 面试时很可能遇到这样一个问题:使用volatile修饰int型变量i,多个线程同时进行i++操作,这样可以实现 ...
-
Java设计模式学习记录-单例模式
前言 已经介绍和学习了两个创建型模式了,今天来学习一下另一个非常常见的创建型模式,单例模式. 单例模式也被称为单件模式(或单体模式),主要作用是控制某个类型的实例数量是一个,而且只有一个. 单例模式 ...
-
JVM学习记录-Java内存模型(二)
对于volatile型变量的特殊规则 关键字volatile可以说是Java虚拟机提供的最轻量级的同步机制. 在处理多线程数据竞争问题时,不仅仅是可以使用synchronized关键字来实现,使用vo ...
-
Java并发——线程同步Volatile与Synchronized详解
0. 前言 转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52370068 面试时很可能遇到这样一个问题:使用volatile修饰in ...
-
Spring 学习记录6 BeanFactory(2)
主题 除了Spring 学习记录5 BeanFactory 里写的几个接口外,BeanFactory的实现类还实现了一些其他接口,这篇文章主要介绍这些接口和实现类. 结构 DefaultListabl ...
-
JavaScript学习记录一
title: JavaScript学习记录一 toc: true date: 2018-09-11 18:26:52 --<JavaScript高级程序设计(第2版)>学习笔记 要多查阅M ...
随机推荐
-
Seo的几个境界
Seo的境界 第一层,弄些关键词排名上去. 是的,大部分人理解的Seoer,就到此为止 这里有技巧若干若干.很值得一些人去卖弄. 第二层,大量广泛的收录,很好的pr值 恭喜您,把握搜索长尾, 这种不显 ...
-
代码重构-4 通用方法 用 static
只要没有用到 this.变量/方法 的,都可以用static 原代码: private string GetPeriodDesc(int lotteryPeriod) { return EnumHe ...
-
influxDB学习总结
1.安装 请参考http://www.cnblogs.com/zhja/p/5996191.html, 安装完毕运行influxd,http://域名:8083为控制台界面:http://域名:808 ...
-
spring3+struts2+hibernate3整合出现的问题,No mapping found for dependency [type=java.lang.String, name=&#39;struts.objectFactory.spring.enableAopSupport&#39;]
七月 11, 2016 3:49:24 下午 org.apache.tomcat.util.digester.SetPropertiesRule begin警告: [SetPropertiesRule ...
-
CenterOS中安装Redis及开机启动设置
Redis安装 从官方下载最新Redis进行安装,官网地址:http://redis.io/download $ wget http://download.redis.io/releases/redi ...
-
【LeetCode】【Python解读】Container with most water
这个问题是芭芭拉在采访中遇到的,不幸的是,的复杂性O(n2)该,太失望了,难怪没有通过面试. Given n non-negative integers a1, a2, ..., an, where ...
-
SharePoint 已在此服务器场中安装 ID 为 XXXXXXXXX 的功能。请使用强制属性显式地重新安装此功能。解决方法
图1: 图2: 解决方法: stsadm -o deploysolution -name ***.wsp -immediate -allowGacDeployment -url http://*** ...
-
Burp Suite Intruder中爆破模式介绍
Burp Suite Intruder中爆破模式介绍 - Introduction to Burst Mode in Burp Suite Intruder 1.sniper模式 使用单一的Payl ...
-
mysql存储过程的学习(mysql提高执行效率之进阶过程)
1:存储过程: 答:存储过程是sql语句和控制语句的预编译集合,以一个名称存储并作为一个单元处理:存储过程存储在数据库内,可以由应用程序调用执行,而且允许用户声明变量以及进行流程控制,存储类型可以接受 ...
-
【刷题】BZOJ 4816 [Sdoi2017]数字表格
Description Doris刚刚学习了fibonacci数列.用f[i]表示数列的第i项,那么 f[0]=0 f[1]=1 f[n]=f[n-1]+f[n-2],n>=2 Doris用老师 ...