当前位置: 首页 > news >正文

自己电脑可以做网站服务器台州百度快照优化公司

自己电脑可以做网站服务器,台州百度快照优化公司,wordpress 博客 页面,wordpress头像无法显示目录 1. 初步认识volatile 2. volatile的特性一#xff1a;保证可见性 2.1 volatile关键字是如何保证可见性的#xff1f; 2.2 从JMM来看可见性 2.3 从硬件层面了解可见性的本质 2.3.1 CPU高速缓存 2.3.2 缓存一致性 2.3.3 MESI 协议 2.3.4 缓存一致性小结 3. vola…目录 1. 初步认识volatile 2. volatile的特性一保证可见性 2.1 volatile关键字是如何保证可见性的 2.2 从JMM来看可见性 2.3 从硬件层面了解可见性的本质 2.3.1 CPU高速缓存 2.3.2 缓存一致性 2.3.3 MESI 协议 2.3.4 缓存一致性小结 3. volatile的特性二禁止指令重排 3.1 什么是指令重排 3.2 重排序的类型有哪些呢源码到最终执行会经过哪些重排序呢 3.3 volatile如何保证不会被执行重排序 3.3.1 volatile写 3.3.2 volatile读 4. volatile的特性三不保证原子性 4.1 为什么volatile不保证原子性 4.2 如何解决原子性问题 5. volatile的应用场景 6.小结 1. 初步认识volatile 下面这段代码演示了一个使用了volatile和没有使用volatile关键字对变量更新的影响。 public class VolatileDemo  {public static void main(String[] args) throws InterruptedException  {VolatileTest test   new VolatileTest();test.start();for  (;;) {if  (test.isFlag()) {System.out.println(hi);}}} } class VolatileTest extends Thread  {private /*volatile*/boolean flag   false;public boolean isFlag() {return flag;}Override public void run() {try  {Thread.sleep(1000);} catch  (Exception ex) {ex.printStackTrace();}flag   true;System.out.println(flag    flag);} } 运行之后会发现如果没加volatile关键字就不会输出 hi 这个结果但是线程中明明改了flag变量的值为什么主线程却访问不到呢这里就要提到volatile在这段代码中所起的作用了。 2. volatile的特性一保证可见性 volatile可以使得在多处理器环境下保证了共享变量的可见性那么到底什么是可见性 一般在单线程的环境下如果向一个变量先写入一个值然后在没有写干涉的情况下读取这个变量的值那么这个时候读取到的这个变量的值应该是之前写入的那个值。 这本来是一件很正常的事件但是在多线程环境下读和写发生在不同的线程中的时候可能会出现以下的情况读线程不能及时的读取到其他线程写入的最新的值。这就是所谓的可见性为了实现跨线程写入的内存可见性必须要使用一些机制来实现而volatile就是这样的一种机制。 2.1 volatile关键字是如何保证可见性的 我们在查看上述代码的汇编指令的时候会发现在修改带有volatile修饰的成员变量时会多出一个lock指令。lock指令是一种控制指令在多线程环境下lock汇编指令可以基于总线锁或者缓存锁的机制来达到可见性的效果。 2.2 从JMM来看可见性 Java内存模型(JavaMemoryModel)描述了Java程序中各种变量(线程共享变量)的访问规则以及在JVM中将变量存储到内存和从内存中读取变量这样的底层细节。 JMM有以下规定 所有的共享变量都存储于主内存这里所说的变量指的是实例变量和类变量不包含局部变量因为局部变量是线程私有的因此不存在竞争问题。 每一个线程还存在自己的工作内存线程的工作内存保留了被线程使用的变量的工作副本。 线程对变量的所有的操作(读取)都必须在工作内存中完成而不能直接读写主内存中的变量。 不同线程之间也不能直接访问对方工作内存中的变量线程间变量的值的传递需要通过主内存中转来完成。 本地内存和主内存的关系 2.3 从硬件层面了解可见性的本质 一台计算机最核心的组件是CPU、内存、以及I/O设备。在整个计算机的发展历程中除了CPU、内存以及I/O设备不断迭代升级来提升计算机处理性能之外还有一个非常矛盾的点就是这三者在处理速度的差异。CPU的处理速度非常快内存次之最后才是I/O设备比如磁盘。为了提升计算性能CPU 从单核升级到了多核甚至用到了超线程技术最大化提高 CPU 的处理性能但是仅仅提升CPU 性能还不够如果后面两者的处理性能没有跟上意味着整体的计算效率取决于最慢的设备。为了平衡三者的速度差异最大化的利用 CPU 提升性能从硬件、操作系统、编译器等方面都做出了很多的优化 CPU 增加了高速缓存 操作系统增加了进程、线程。通过 CPU 的时间片切换最大化的提升 CPU 的使用率 编译器的指令优化更合理的去利用好 CPU 的高速缓存然后每一种优化都会带来相应的问题而这些问题也是导致线程安全性问题的根源。为了了解前面提到的可见性问题的本质我们有必要去了解这些优化的过程 2.3.1 CPU高速缓存 线程是 CPU 调度的最小单元线程设计的目的最终仍然是更充分的利用计算机处理的效能但是绝大部分的运算任务不能只依靠处理器“计算”就能完成处理器还需要与内存交互比如读取运算数据、存储运算结果这个 I/O 操作是很难消除的。而由于计算机的存储设备与处理器的运算速度差距非常大所以现代计算机系统都会增加一层读写速度尽可能接近处理器运算速度的高速缓存来作为内存和处理器之间的缓冲将运算需要使用的数据复制到缓存中让运算能快速进行当运算结束后再从缓存同步到内存之中。 CPU高速缓存 上图中L1 高速缓存和 L2 高速缓存都只能被一个单独的 CPU 内核使用L3 高速缓存可以被同一个插槽上的 CPU 内核共享主存由全部插槽上的所有 CPU 核共享。CPU 读取数据时先从 L1 中读取如果没有命中再到 L2、L3 中读取假如这些高速缓存都没有命中它就会到主存中找所需要的数据。通过高速缓存的存储交互很好的解决了处理器与内存的速 度矛盾但是也为计算机系统带来了更高的复杂度因为它引入了一个新的问题缓存一致性。 2.3.2 缓存一致性 首先有了高速缓存的存在以后每个 CPU 的处理过程是先将计算需要用到的数据缓存在 CPU 高速缓存中在 CPU进行计算时直接从高速缓存中读取数据并且在计算完成之后写入到缓存中。在整个运算过程完成后再把缓存中的数据同步到主内存。由于在多 CPU 种每个线程可能会运行在不同的 CPU 内并且每个线程拥有自己的高速缓存。同一份数据可能会被缓存到多个 CPU 中如果在不同 CPU 中运行的不同线程看到同一份内存的缓存值不一样就会存在缓存不一致的问题为了解决缓存不一致的问题在 CPU 层面做了很多事情主要提供了两种解决办法 总线锁 总线锁简单来说就是在多 cpu 下当其中一个处理器要对共享内存进行操作的时候在总线上发出一个 LOCK#信号这个信号使得其他处理器无法通过总线来访问到共享内存中的数据总线锁定把 CPU 和内存之间的通信锁住了这使得锁定期间其他处理器不能操作其他内存地址的数据所以总线锁定的开销比较大这种机制显然是不合适的。如何优化呢最好的方法就是控制锁的保护粒度我们只需要保证对于被多个 CPU 缓存的同一份数据是一致的就行。所以引入了缓存锁它核心机制是基于缓存一致性协议来实现的。缓存锁 相比总线锁缓存锁即降低了锁的力度。为了达到数据访问的一致需要各个处理器在访问缓存时遵循一些协议在读写时根据协议来操作常见的协议有 MSI、MESI、MOSI 等。最常见的就是 MESI 协议。2.3.3 MESI 协议 目前主流缓存一致性协议为 MESI 写入失效协议在 MESI 协议中每个缓存行Cache line有 4 种状态M、E、S 和 I全名是 Modified、Exclusive、 Share、Invalid代表使用缓存行所处的 4 种状态可用 2 个 bit 表示。缓存行Cache line是缓存操作的基本单位在 Intel 的 CPU 上一般是 64 字节。 MESI 阐述原理 MESI 协议是以缓存行的 4 种状态的首字母缩写来命名的。该协议要求在每个缓存行上维护两个状态位使得每个数据单位可能处于 M、E、S 和 I 这 4 种状态之一各种状态含义如下 1M: 被修改Modified 该缓存行的数据只在本 CPU 的私有 Cache 中进行了缓存而其他 CPU 中没有并且是被修改过Dirty)即与主存中的数据不一致且没有更新到内存中。该缓存行中的内存需要在未来的某个时间点允许其他 CPU 读取请主存中相应内存之前写回Write Back到主存。当被写回主存之后该缓存行的状态会变成独享Exclusive)状态。简单来说处于 Modified 状态的缓存行数据只有在本 CPU 中有缓存且其数据与内存中的数据不一致数据被修改过。 2E: 独享的Exclusive 该缓存行的数据只在本 CPU 的私有 Cache 中进行了缓存而其他 CPU 中没有缓存行的数据是未被修改过的Clean并且与主存中数据一致。该状态下的缓存行如果在任何时刻被其 他 CPU 读取之后其状态变成共享状态Shared)。在本 CPU 修改了缓存行中数据后该缓存行状态可以变成 Modified 状态。简单来说处于 Exclusive 状态的缓存行数据只有在本 CPU 中有缓存且其数据与内存中一致没有被修改过。 3S: 共享的Shared 该缓存行的数据可能在本 CPU 以及其他 CPU 的私有 Cache 中进行了缓存并且各 CPU 私 有 Cache 中的数据与主存数据一致Clean)当有一个 CPU 修改该缓存行其他 CPU 中该缓存行将被作废变成无效状态Invalid。简单的说处于 Shared 状态的缓存行的数据在多个 CPU 中都有缓存且与内存一致。 4I: 无效的Invalid 该缓存行是无效的可能有其他 CPU 修改了该缓存行。 CPU 读请求缓存处于 M、E、S 状态都可以被读取I 状 态 CPU 只能从主存中读取数据 CPU 写请求缓存处于 M、E 状态才可以被写。对于 S 状态的写需要将其他 CPU 中缓存行置为无效才可写 任意一个 CPU Core 的私有缓存行与其他 CPU Core 私有缓存行的相容关系如图所示 缓存行的相容关系 2.3.4 缓存一致性小结 当CPU写数据时如果发现操作的变量是共享变量即在其他CPU中也存在该变量的副本会发出信号通知其他CPU将该变量的缓存行置为无效状态因此当其他CPU需要读取这个变量时发现自己缓存中缓存该变量的缓存行是无效的那么它就会从内存重新读取。 每个处理器通过嗅探在总线上传播的数据来检查自己缓存的值是不是过期了当处理器发现自己缓存行对应的内存地址被修改就会将当前处理器的缓存行设置成无效状态当处理器对这个数据进行修改操作的时候会重新从系统内存中把数据读到处理器缓存里。 由于volatile的MESI缓存一致性协议需要不断的从主内存嗅探和cas不断循环无效交互会导致总线带宽达到峰值会引发总线风暴所以不要大量使用volatile至于什么时候去使用Volatile什么时候使用锁根据场景区分。 3. volatile的特性二禁止指令重排 3.1 什么是指令重排 重排序是指编译器和处理器为了优化程序性能而对指令序列进行重新排序的一种手段。 3.2 重排序的类型有哪些呢源码到最终执行会经过哪些重排序呢 指令重排 一个好的内存模型实际上会放松对处理器和编译器规则的束缚也就是说软件技术和硬件技术都为同一个目标而进行奋斗在不改变程序执行结果的前提下尽可能提高执行效率。 JMM对底层尽量减少约束使其能够发挥自身优势。 因此在执行程序时为了提高性能编译器和处理器常常会对指令进行重排序。 一般重排序可以分为如下三种 编译器优化的重排序。编译器在不改变单线程程序语义的前提下可以重新安排语句的执行顺序; 指令级并行的重排序。现代处理器采用了指令级并行技术来将多条指令重叠执行。如果不存在数据依赖性处理器可以改变语句对应机器指令的执行顺序; 内存系统的重排序。由于处理器使用缓存和读/写缓冲区这使得加载和存储操作看上去可能是在乱序执行的。 这里还得提一个概念as-if-serial。 不管怎么重排序单线程下的执行结果不能被改变。 编译器、runtime和处理器都必须遵守as-if-serial语义。 3.3 volatile如何保证不会被执行重排序 java编译器会在生成指令系列时在适当的位置会插入内存屏障指令来禁止特定类型的处理器重排序。 为了实现volatile的内存语义JMM会限制特定类型的编译器和处理器重排序JMM会针对编译器制定volatile重排序规则表 volatile重排序规则表 需要注意的是volatile写是在前面和后面分别插入内存屏障而volatile读操作是在后面插入两个内存屏障。 3.3.1 volatile写 volatile写 3.3.2 volatile读 volatile读 4. volatile的特性三不保证原子性 所谓原子性就是不可分割也即某个线程在做某个具体业务时中间不可以被加塞或者分割需要整体完整要么同时成功 要么同时失败。 看下如下代码 public class VolatileAtomic  {public static void main(String[] args) {MyTest myTest  new MyTest();for (int i   1; i   20; i) {new Thread(()  -   {for  (int j   1; j   1000; j) {myTest.addNum();}},String.valueOf(i)).start();}while (Thread.activeCount() 2) {Thread.yield();}System.out.println(Thread.currentThread().getName() \t number myTest.num);} }class MyTest  {public volatile int num   0;public void addNum() {num;} } 添加了volatile最终结果应该为20000然而结果小于等于20000说明volatile不保证原子性。 运行结果 4.1 为什么volatile不保证原子性 是因为num在多线程下是非线程安全的。 num方法编译成字节码后分为以下三步运行的 1.从主存中复制 i 的值并复制到 CPU 的工作内存中。 2.CPU 取工作内存中的值然后执行 i操作完成后刷新到工作内存。 3.将工作内存中的值更新到主存。原本线程1在自己的工作空间中将num改为1写回主内存主内存由于内存可见性通知线程2 3num1线程2通过变量的副本拷贝将num拷贝并num2再次写入主内存通知线程3num2线程3通过变量的副本拷贝将num拷贝并num3 然而 多线程竞争调度的原因1号线程刚刚要写1的时候被挂起2号线程将1写入主内存此时应该通知其他线程主内存的值更改为1由于线程操作极快还没有通知到其他线程刚才被挂起的线程1 将num1 又再次写入了主内存主内存的值被覆盖出现了丢失写值 4.2 如何解决原子性问题 这种问题可以使用synchronized 或者使用原子变量 来解决。原子变量通过调用unsafe类的cas方法实现了原子操作由于CAS是一种系统原语,原语属于操作系统用于范畴,是由若干条指令组成,用于完成某个功能的一个过程,并且原语的执行必须是连续的,在执行过程中不允许中断,也即是说CAS是一条原子指令,不会造成所谓的数据不一致的问题。 5. volatile的应用场景 DCLDouble Check Lock双端检索机制 双端检索机制不一定安全原因是有指令重排序的存在加入volatile可以禁止指令重排。 在某一个线程执行到第一次检测时此时instance不为null但是insatnce的引用对象可能没有初始化完成 public class Singleton  {public volatile static Singleton singleton;public static Singleton getInstance() {if  (singleton   null) {synchronized  (Singleton.class) {// 若为空才进行对象创建防止对象重复创建if  (singleton   null) {// 使用volatile防止重排序造成的异常singleton   new Singleton();}}}return singleton;} } 在某一个线程执行第一次检测时此时读取到的instance不为空但是instance得到引用对象可能没有完成初始化。 Instance   new Singleton();可以分为以下三步Memory   allocate(); //1.分配对象内存空间 Instance(memory) //2.初始化对象 Instance   memeory  //3.设置初始化的对象指向刚分配的内存地址此时instacne ! null步骤2和步骤3不存在数据依赖关系所以这种重排序是允许的 Memory  allocate(); Instance  memeory Instance(memory)//2.初始化对象 所以这个时候出现的问题为多个线程在这里获得单例对象第一个访问者在instance new Singleton();这一步骤时由于指令重排序底层先给对象分配好了地址此时不为空这个时候其他线程访问instacne不为空但是得不到实例对象。 6.小结 volatile是java虚拟机提供的轻量级的同步机制主要有以下几点 1.保证可见性 2.禁止指令重排 3.不保证原子性 4.volatile只能作用于属性我们用volatile修饰属性这样compilers就不会对这个属性做指令重排序。 5.volatile可以在单例双重检查中实现可见性和禁止指令重排序从而保证安全性。
http://www.pierceye.com/news/792427/

相关文章:

  • 成都网站建设企业 排名网络营销推广方案ppt
  • 阳西住房和城乡规划建设局网站微信公众号商城制作
  • 石家庄自助建站软件邯郸做紧固件网站
  • 做川菜的网站动画制作网页
  • 网站建设的英文域名注册需要什么条件
  • wordpress管理系统贵州seo和网络推广
  • 网站第二次备案设计方案审核合格后由谁签字确认
  • 网页设计和网站编辑wordpress 页面瀑布流
  • 福田网站建设龙岗网站建设ie的常用网站
  • 网站推广途径和推广要点地产网站方案
  • 用asp做的网站2021互联网公司100强
  • 网站运营无经验可以做吗垂直类网站怎么做
  • 中国站长网站wordpress开启xmlrpc
  • 网站建设的好处建设工程质量管理条例网站
  • asp.net网站建设教程做电影网站 需要进那些群
  • 2013网站挂马教程长沙网站建设优化
  • 网站搭建详细教程wordpress 找不到主题
  • 陕西省建设厅申报网站大型网站建设公司推荐
  • 企业商城建站外贸建站上海
  • 织梦如何做网站网页设计公司背景
  • 购买域名网站程序员外包公司到底值不值得去
  • 网站出售商品建设广告公司主要做什么
  • 西安的电商网站设计大庆市城乡建设局网站
  • 服装网站建设需要什么内容中国建设银行总行官方网站
  • 免费下载设计素材网站wordpress metaslider
  • 如何建一个自己的网站给网站做rss
  • 宜昌网站制作公司亿腾云优化seo
  • 网站icp备案信息是什么一号网站建设
  • 怎么样做网站徐州市中宇建设工程有限公司网站
  • 网站建站公司官网免费企业网站建设介绍