在多线程中我们常用的保证共享变量的方法有很多,现在我们介绍其中的一种,volatile,也是效率最高的一种。

   一 、volatile的意义:
            为了确保共享变量能被正确和一致的更新,字段被声明称volatile,java线程内存模型确保所有线程看到这个变量的值是一致的。volatile变量修饰符如果使用恰当的话,它比synchronize的使用和执行成本更低,因此它不会引起线程上下文的切换和调度。
 
   二 、如何保证所有线程看到的这个变量的值是一致的?
 源码中有这样一句, instance = new Singleton();说明这是一个单例,任何线程请求的都是这一个对象。生成汇编代码:

 在汇编代码中会出现 一个lock前缀,有这个前缀会发生两件事:
1.当前处理器的缓存行的数据都会写回到系统内存。
2.这个写回内存的操作会引起其他CPU缓存的该内存地址的数据无效。
为什么好多的都设64个字节,或是hash的一些默认空间设置成16个,原因与处理器结构有关,一般处理器缓存的额告诉缓存行时64个字节宽,换句话说他可以放16个对象,所以追加字节能优化性能。一些我们常见的java集合都是默认的设置空间为16。
  三 、 与Synchronize、lock的区别
       1.synchronize是一种机制,可加在方法上,也可以加载语句块上;lock是一个对象,多线程需要一个ReentrantLock才能实现锁机制。

       2.synchronize是托管给JVM管理的,lock是java代码写的控制锁的实现。
       3.synchronized采用的是悲观锁机制,线程获得的是独占锁,只能依靠阻塞来等待线程释放锁。而且CPU转换线程时上下文切换回引起新城竞争锁,使得效率降低。lock 采用的是乐观锁机制,乐观锁其实就是不加锁,一直去操作,失败就重新操作,直到成功为止,效率高很多。
4.当竞争不激烈的时候synchronize的性能好一点儿,但是当竞争激烈的时候lock的性能要很多。

四 、在JVM中锁是如何工作的:

         1.java对象头:hashcode,锁,分代年龄。在运行期间MarkWord 里存储的数据会随着锁标志位的变化而变化,可能变化为下面的数据:

多线程---再次认识volatile,Synchronize,lock的更多相关文章

  1. C#多线程-volatile、lock关键字

    volatile是C#中最简单的一种同步关键字,其意义是针对程序中一些敏感数据,不允许多线程同时访问,保证数据在任何访问时刻,最多有一个线程访问,以保证数据的完整性,虽与java中的synchroni ...

  2. 并行编程之多线程共享非volatile变量,会不会可能导致线程while死循环

    背景 大家都知道线程之间共享变量要用volatilekeyword.可是,假设不用volatile来标识,会不会导致线程死循环?比方以下的伪代码: static int flag = -1; void ...

  3. “全栈2019”Java多线程第二十七章:Lock获取lock/释放unlock锁

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  4. .NET多线程之线程安全,Lock(锁)、Monitor(同步访问)、LazyInitializer(延迟初始化)、Interlocked(原子操作)、static(静态)构造函数、volatile、

    1.什么是线程安全 线程安全是编程中的术语,指某个函数.函数库在多线程环境中被调用时,能够正确地处理多个线程之间的共享变量,使程序功能正确完成.一般来说,线程安全的函数应该为每个调用它的线程分配专门的 ...

  5. java多线程关键字volatile、lock、synchronized

    --------------------- 本文来自 旭日Follow_24 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/xuri24/article/detail ...

  6. Java多线程学习(六)Lock锁的使用

    系列文章传送门: Java多线程学习(二)synchronized关键字(1) Java多线程学习(二)synchronized关键字(2) Java多线程学习(三)volatile关键字 Java多 ...

  7. JMM内存模型+volatile+synchronized+lock

    硬件内存模型: Java内存模型: 每个线程都有一个工作内存,线程只可以修改自己工作内存中的数据,然后再同步回主内存,主内存由多个内存共享. 下面 8 个操作都是原子的,不可再分的: 1)  lock ...

  8. Java多线程编程(四)Lock的使用

    一.使用ReentrantLock类 在Java多线程中,可以使用synchronized关键字来实现线程之间的同步互斥,但ReentrantLock类也能达到同样的效果,并且在扩展功能上也更加强大, ...

  9. volatile与lock前缀指令

    前言 我们知道volatile关键字的作用是保证变量在多线程之间的可见性,它是java.util.concurrent包的核心,没有volatile就没有这么多的并发类给我们使用. 本文详细解读一下v ...

随机推荐

  1. C++用new来创建对象和非new来创建对象的区别

    转:http://www.cnblogs.com/GODYCA/archive/2013/01/10/2854777.html 我们都知道C++中有三种创建对象的方法,如下: #include < ...

  2. Logstash写入MongoDB数据库

    1. 列出logstash-plugins bin/logstash-plugin list****** logstash-output-kafkalogstash-output-nagioslogs ...

  3. HttpClient request payload post请求

    RequestEntity entity = new StringRequestEntity(str, "text/html", "utf-8"); post. ...

  4. Python版求数组的最大连续区间

    [本文出自天外归云的博客园] 题目:有一个数组,求他的最大(最长)连续区间(数字是连续的区间). 我的解法,如下: class Finder(object): ''' 判断两个相邻的数字是否连续,若连 ...

  5. ios 根据scrollview滑动的偏移计算滑动到第几页算法(不同需求不同计算)

    第一种: CGFloat pageWidth = self.scrollView.frame.size.width; int page = floor((self.scrollView.content ...

  6. curl Array to string conversion 错误

    0x00 故障 由于GuzzleHttp在iis上使用错误,于是开始替换其为Unirest,没想到发送了一个curl Array to string conversion 错误 0x01 原因 跟踪调 ...

  7. Laravel Eloquent使用小记

    原文地址:http://blog.onlywan.cc/14843810761202.html Laravel Eloquent使用小记 今天由于开发数据库业务中间层须要.開始研究Laravel El ...

  8. ADO对Excel对象进行连接时的 两种方法区别

    在通过ADO对Excel对象进行连接时(此时Excel则认为是一个数据源),需要配置对Excel数据源对应的连接串,这个连接串中包括了Provider信息(其实类似对数据库进行连接操作时,都需要指定连 ...

  9. JVM——代空间的划分

    首先看在JVM的堆中,按代的划分: Young:主要是用来存放新生的对象. Old:主要存放应用程序中生命周期长的内存对象. Permanent:是指内存的永久保存区域,主要存放Class和Meta的 ...

  10. JDK观察者模式和事件机制比较<转>

    原文:(六)观察者模式详解(包含观察者模式JDK的漏洞以及事件驱动模型) 作者:zuoxiaolong8810(左潇龙),转载请注明出处. 本章我们讨论一个除前面的单例以及代理模式之外,一个WEB项目 ...