背景:听说Volatile Java高阶语法亦是挺进BAT的必经之路。

Volatile:

volatile同步机制又涉及Java内存模型中的可见性、原子性和有序性,恶补基础一波。

可见性:

可见性简单的说是线程之间的可见性,一个线程修改的状态对另一个线程是可见对,也就是一个线程的修改结果另一个线程可以马上看到;但通常,我们无法确保执行读操作的线程能够时时的看到其他线程写入的值,So为了确保多个线程之间对内存写入操作可见性,必须使用同步机制;如用volatile修饰的变量就具有可见性,volatile修饰的变量不允许线程内部缓存和重排序,而是直接修改内存,所以对其他线程来说是可见的;但volatile只能保证被修饰的内容具有可见性,并不具备原子性,如volatile int vipNumber = 100,之后有一个vipNumber++ 的操作,这个变量vipNumber具有可见性,但是vipNumber++ 依然是一个非原子操作,也就是说这个操作同样存在线程安全问题。

原子性:

原子具有不可分割的特性,如int age = 22,这个操作是不可分割的,那么称其为原子操作,具有原子性;再比如age++,这个操作实际是age = age + 1,其是可分割的,So它不是一个原子操作;而非原子操作都会存在线程安全问题,需要我们使用同步技术(synchronized)来让它变成一个原子操作;Java的concurrent包下提供了一些原子类,如:AtomicLongMap、AtomicDouble、AtomicReference 等;在Java中用synchronized、lock和unlock来保证原子性。

有序性:

Java语言提供了volatile和synchronized两个关键字来保证线程之间操作的有序性,volatile是因为本身包含“禁止指令重排序”的语义,synchronized是由“一个变量在同一时刻只允许一条线程对其进行lock操作”这条规则获得有序性的,此规则决定了持有同一个对象锁的两个同步块只能串行执行。

Volatile原理:

volatile是一种稍弱的同步机制,其用来确保将变量的更新操作通知到其他线程;当变量声明为volatile类型后,编译器与JVM运行时都会注意到这个变量时共享的,因此不会将此变量上的操作与其他操作一起重排序;volatile修饰后变量不会缓存在寄存器或者对其他处理器不可见的地方,因此在单曲volatile类型的变量时总会返回最新写入的值;除此之外,在访问volatile变量时不会执行加锁操作,也就不会执行线程阻塞,因此volatile变量是一种比synchronized关键字更轻量级的同步机制;当对非volatile变量进行读写时,每个线程从内存拷贝变量到CPU缓存中,如果计算机有多个CPU则每个线程可能在不同的CPU上被处理,这就意味着每个线程都可以拷贝到不同的CPU缓存cache中,而不是像volatile变量那样直接读内存,JVM保证其每次读变量都从内存中读,跳过了CPU cache这一步骤。

当一个变量定义为volatile之后,其具备的两种特征:

1、保证此变量对所有的线程的可见性;当一个线程修改了此变量的值,volatle保证新值能够立即同步到主内存,以及每次使用前立即从主每次刷新;

2、禁止指令重排序优化;被volatile修饰的变量赋值后多执行了一个“load”操作,此操作相当于一个内存屏障(指令重排序时不能把后面的指令重排序到内存屏障之前到位置),只有一个CPU访问内存时,不需要内存屏障;(指令重排序:指CPU采用了允许将多条指令不按程序规定的顺序分开发送给各相应电路单元处理)

另外:在性能方面,volatile的读操作性能消耗与普通变量基本无异,但是写操作稍慢,因为它需要在本地代码中插入许多内存屏障来保证处理器不发生乱序执行。

这里撸了一个例子用volatile保证线程间的同步,如果变量author不经volatile修饰,线程2中对author的值做了修改并未同步到线程1中,其一直存在缓存中。

FYI:

1 importlombok.extern.slf4j.Slf4j;2

3 @Slf4j4 public classTestVolatile {5 //private volatile String author = "tjt";//volatile修饰author保证两个线程到可见性,即不存在缓存cache中

6 private String author = "tjt"; //不用volatile修饰变量author则author修改值后在线程之间并不可见

7 private boolean enable = false;8 public static void main(String[] args) throwsException {9 TestVolatile testVolatile = newTestVolatile();10 log.info("原始定义的author: "+testVolatile.author);11 Thread thread = new Thread( newRunnable() {12 @Override13 public voidrun() {14 testVolatile.testMethodOne();15 }16 });17 thread.start();18 thread.sleep(2000l);19 testVolatile.testMethodTwo();20 }21 public voidtestMethodOne() {22 while(true) {23 if ("detect_tjt".equals(author) && enable == false) {24 log.info("线程testMethodOne中检测到来author修改为: "+author);25 enable = true;26 System.exit(0);27 }28 } }29 public voidtestMethodTwo() {30 author = "detect_tjt";31 log.info("线程testMethodTwo中把author修改为: "+author);32 }33 }

用volatile修饰author执行结果:

- 原始定义的author: tjt

- 线程testMethodTwo中把author修改为: detect_tjt

- 线程testMethodOne中检测到来author修改为: detect_tjt

无volatile修饰author执行结果:

- 原始定义的author: tjt

- 线程testMethodTwo中把author修改为: detect_tjt

Java高阶代码_Java高阶语法---Volatile相关推荐

  1. java多线程死锁代码_java多线程死锁 编写高质量代码:改善Java程序的151个建议...

    java多线程死锁 编写高质量代码:改善Java程序的151个建议 第1章 Java开发中的通用方法和准则 建议1:不要在常量和变量中出现易混淆的字母 建议2:莫让常量蜕变成变量 建议3:三元操作符的 ...

  2. java 内存模型 多线程_Java 高并发三:Java内存模型和线程安全详解

    网上很多资料在描述Java内存模型的时候,都会介绍有一个主存,然后每个工作线程有自己的工作内存.数据在主存中会有一份,在工作内存中也有一份.工作内存和主存之间会有各种原子操作去进行同步. 下图来源于这 ...

  3. java 生产者消费者代码_Java生产者和消费者代码

    java 生产者消费者代码 This also helps us to understand the concept of synchronised multi-threading in java, ...

  4. 短链接java代码_java高仿新浪微博短链接地址生成工具ShortUrlGenerator.java

    仿新浪微博 短链接地址生成工具 ShortUrlGenerator.java String sLongUrl = "http://tech.sina.com.cn/i/2011-03-23/ ...

  5. java拯救苹果代码_java swing游戏编程高仿金山打字教程-拯救苹果

    import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Image; import ...

  6. java高并发类_Java 高并发之魂

    前置知识 了解Java基本语法 了解多线程基本知识 知识介绍 Synchronized简介:作用.地位.不控制并发的后果 两种用法:对象锁和类锁 多线程访问同步方法的7种情况:是否是static.Sy ...

  7. java如何保证数据安全_java高并发下怎么保障数据安全?有哪些办法?

    近些年科技发展水平越来越快速了,这也促使了大家对于新兴软件的学习.尤其是对于java的渴求更是明显,这也进一步说明了java功能的强大.今天就来为大家介绍一下java高并发下怎么保障数据安全以及有哪些 ...

  8. java面向对象基础代码_Java基础语法——面向对象(1)

    一 面向对象 1.1 什么是面向过程.面向对象 面向过程与面向对象都是我们编程中,编写程序的一种思维方式. 面向过程的程序设计方式,是遇到一件事时,思考"我该怎么做",然后一步步实 ...

  9. java service层 事务_Java高并发秒时啊API之Service层1

    ---2-1 使用Spring托管Service依赖理论---------------------------- spring ioc优势(工厂模式): 1.对象创建统一托管 2.规范的生命周期管理 ...

最新文章

  1. java.security.InvalidKeyException: Illegal key size or default parameters
  2. web项目中关于引入JS/css文件, 浏览器console出现 net::ERR_ABORTED错误的解决方法
  3. leetcode: 树
  4. C++ Prime:范围for语句
  5. 豆瓣评分9分+,每一部看完不禁感慨!这里是神州大地!
  6. 【Jmeter篇】jmeter+Ant+Jenkins接口自动化测试集成之报告优化(三)
  7. k-means算法的matlab代码实现_MATLAB遗传算法及其实现
  8. Ruby on Rails 和 J2EE:两者能否共存?
  9. 对datatable类型列名排序_表格数据的排序功能(支持多列)
  10. 均薪连续三年过万,北上深人才需求大 !| 5G 人才报告
  11. php--学习封装类 (一)(操作mysql数据库的数据访问)
  12. Mac编译OpenJDK8:configure: error: Xcode 4 is required to build JDK 8, the version found was 10.1config
  13. C# 同一应用程序域不同线程之间的参数传递方式
  14. 数据分析师必备的python包
  15. 我的tudo日记2(关于babel和postcss)
  16. kubebuilder之一:kubernetes operator工作原理
  17. aptana手动配置python环境_Aptana Studio 3配置Python开发环境图文教程
  18. 解决vender-base.66c6fc1c0b393478adf7.js:6 TypeError: Cannot read property ‘validate‘ of undefined问题
  19. Redis统计用户访问量
  20. 保护手机隐私最关键是提高全民信息安全意识

热门文章

  1. Android4: HDMI system in ICS
  2. volatile的作用(转自于http://www.csdn.net/)——今天差点忘记了!
  3. vue-cli中的webpack配置
  4. leetcode 8. String to Integer (atoi)
  5. Hive 和普通关系数据库的异同
  6. Mybatis解决字段名与实体类属性名不相同的冲突
  7. 【涛声依旧】华为的“大服务”
  8. solrcloud replica collection core shard slice 概念讲解
  9. T-SQL查询——数据集之间的运算
  10. 批处理(.bat)无限循环,定时,固定时间间隔