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

在家建设一个网站需要什么手续搜索引擎排名优化公司

在家建设一个网站需要什么手续,搜索引擎排名优化公司,搜索引擎推广案例,天津业之峰装修公司地址文章目录 JUC之Java内置锁的核心原理Java对象结构对象头对象体对齐字节 Mark Word的结构信息64位Mark Word的构成 偏向锁偏向锁的设置偏向锁的重偏向偏向锁的撤销偏向锁的膨胀 轻量级锁执行过程轻量级锁的分类普通自旋锁自适应自旋锁 重量级锁偏向锁、轻量级锁与重量级锁的对比…

文章目录

      • JUC之Java内置锁的核心原理
        • Java对象结构
          • 对象头
          • 对象体
          • 对齐字节
        • Mark Word的结构信息
          • 64位Mark Word的构成
        • 偏向锁
          • 偏向锁的设置
          • 偏向锁的重偏向
          • 偏向锁的撤销
          • 偏向锁的膨胀
        • 轻量级锁
          • 执行过程
          • 轻量级锁的分类
            • 普通自旋锁
            • 自适应自旋锁
        • 重量级锁
        • 偏向锁、轻量级锁与重量级锁的对比

JUC之Java内置锁的核心原理

​ Java内置锁是一个互斥锁,这就意味着最多只有一个线程能够获 得该锁,当线程B尝试去获得线程A持有的内置锁时,线程B必须等待或 者阻塞,直到线程A释放这个锁,如果线程A不释放这个锁,那么线程B 将永远等待下去。

​ Java中每个对象都可以用作锁,这些锁称为内置锁。线程进入同 步代码块或方法时会自动获得该锁,在退出同步代码块或方法时会释 放该锁。获得内置锁的唯一途径就是进入这个锁保护的同步代码块或 方法。

Java对象结构

Java对象(Object实例)结构包括三部分:对象头、对象体和对齐字节。

结构如下:

在这里插入图片描述

对象头

​ 对象头包括三个字段,第一个字段叫作Mark Word(标记字),用于存储自身运行时的数据,例如GC标志位、哈希码、锁状态信息等。

​ 第二个字段叫作Class Pointer(类对象指针),用于存放方法区Class对象的地址,虚拟机通过这个指针来确定这个对象是哪个类的实例。

​ 第三个字段叫作Array Length(数组长度)。如果对象是一个Java数组,那这个字段必须要有,用于记录数组长度的数据;如果对象不是一个Java数组,那么此字段不存在,所以这是一个可选字段。

对象体

​ 对象体包含对象的实例变量(成员变量),用于成员属性值,包括父类的成员属性值。这部分内存按4字节对齐。对象体是对象的主体部分,占用的内存空间大小取决于对象的属性数量和类型。

对齐字节

​ 对齐字节也叫作填充对齐,其作用是用来保证Java对象所占内存 字节数为8的倍数HotSpot VM的内存管理要求对象起始地址必须是8字 节的整数倍。对象头本身是8的倍数,当对象的实例变量数据不是8的 倍数时,便需要填充数据来保证8字节的对齐。

​ 对齐字节并不是必然存在的,也没有特别的含义,它仅仅起 着占位符的作用。当对象实例数据部分没有对齐(8字节的整数倍) 时,就需要通过对齐填充来补全。

Mark Word的结构信息

​ Java内置锁涉及很多重要信息,这些都存放在对象头的Mark Word字段中。Mark Word不会受到Oop指针压缩选项的影响。Java内置锁的状态总共有4种,级别由低到高依次为:无锁、偏向锁、轻量级锁和重量级锁。在JDK1.6之前只有重量级锁,之后才引入偏向锁和轻量级锁。4种锁状态会随着竞争的情况逐渐升级,而且不可逆,即只能进行锁升级,不会发生锁降级。

不同锁状态下32位Mark Work的结构信息:

在这里插入图片描述

不同锁状态下64位Mark Work的结构信息:

在这里插入图片描述

64位Mark Word的构成
  1. lock:锁状态标记位,占两个二进制位。该标记的 值不同,整个Mark Word表示的含义就不同。
  2. biased_lock:对象是否启用偏向锁标记,只占1个二进制 位。为1时表示对象启用偏向锁,为0时表示对象没有偏向锁。
  3. age:4位的Java对象分代年龄。在GC中,对象在Survivor区 复制一次,年龄就增加1。当对象达到设定的阈值时,将会晋升到老年 代。默认情况下,并行GC的年龄阈值为15,并发GC的年龄阈值为6。由 于age只有4位,因此最大值为15,这就是-XX:MaxTenuringThreshold 选项最大值为15的原因。
  4. identity_hashcode:31位的对象标识HashCode(哈希码) 采用延迟加载技术,当调用Object.hashCode()方法或者 System.identityHashCode()方法计算对象的HashCode后,其结果将被 写到该对象头中。当对象被锁定时,该值会移动到Monitor(监视器) 中。
  5. thread:54位的线程ID值为持有偏向锁的线程ID。
  6. epoch:偏向时间戳。
  7. ptr_to_lock_record:占62位,在轻量级锁的状态下指向栈帧中锁记录的指针。
  8. ptr_to_heavyweight_monitor:占62位,在重量级锁的状态下指向对象监视器的指针。

32位的Mark Word与64位的Mark Word结构相似

偏向锁

​ 如果一个同步块(或方法)没有多个线程竞争, 而且总是由同一个线程多次重入获取锁,如果每次还有阻塞线程,唤 醒CPU从用户态转为核心态,那么对于CPU是一种资源的浪费,为了解 决这类问题,就引入了偏向锁的概念。偏向锁主要解决无竞争下的锁性能问题,所谓的偏向就是偏心, 即锁会偏向于当前已经占有锁的线程。

​ 原理:如果不存在线程竞争的一个线程获得了锁,那么锁就进入偏向状态,此时Mark Word的结构变为偏向锁结构, 锁对象的锁标志位(lock)被改为01,偏向标志位(biased_lock)被改为1,然后线程的ID记录在锁对象的Mark Word中(使用CAS操作完 成)。以后该线程获取锁时判断一下线程ID和标志位,就可以直接进 入同步块,连CAS操作都不需要,这样就省去了大量有关锁申请的操作,从而也就提升了程序的性能。

偏向锁的设置

​ 如果开启了偏向锁(默认开启),那么对象创建后,markword值为0x05即最后3位为101,这时它的thread、epoch、age都为0;如果没有开启偏向锁,那么对象创建后,markword值为0x01即最后3位位001,这时它的hashcode、age都为0,第一次用到hashcode时才会赋值。使用-XX:-UseBiasedLocking可以禁用偏向锁。

​ 偏向锁是默认延迟的,不会在程序启动时立即生效,如果想避免延迟,可以加VM参数-XX:BiasedLockingStartupDelay=0 来禁用延迟。

偏向锁的重偏向

​ 如果对象虽然被多个线程访问,但没有竞争,这时偏向了线程T 1 的对象仍有机会重新偏向T 2 ,重偏向会重置对象的 Thread ID。当撤销偏向锁阈值超过20次后,(从第二十次开始)jvm之后在给这些对象加锁时重新加偏向锁至新的线程。

偏向锁的撤销

偏向锁的撤销过程:

  1. 在一个安全点停止拥有锁的线程。
  2. 遍历线程的栈帧,检查是否存在锁记录。如果存在锁记录, 就需要清空锁记录,使其变成无锁状态,并修复锁记录指向的Mark Word,清除其线程ID。
  3. 将当前锁升级成轻量级锁。
  4. 唤醒当前线程。

​ 所以,如果某些临界区存在两个及两个以上的线程竞争,那么偏 向锁反而会降低性能。在这种情况下,可以在启动JVM时就把偏向锁的 默认功能关闭。

撤销偏向锁的情况:

  1. 多个线程竞争偏向锁。
  2. 调用偏向锁对象的hashcode()方法或者 System.identityHashCode()方法计算对象的HashCode之后,将哈希码 放置到Mark Word中,内置锁变成无锁状态,偏向锁将被撤销。
  3. 调用 wait/notify,这个只有重量级锁才有

当撤销偏向锁阈值超过40次后,(从第四十次开始)jvm会将整个类的所有对象都变为不可偏向的,新建的对象也会是不可偏向的。

偏向锁的膨胀

​ 如果偏向锁被占据,一旦有第二个线程争抢这个对象,因为偏向 锁不会主动释放,所以第二个线程可以看到内置锁偏向状态,这时表 明在这个对象锁上已经存在竞争了。JVM检查原来持有该对象锁的占有 线程是否依然存活,如果挂了,就可以将对象变为无锁状态,然后进 行重新偏向,偏向为抢锁线程。

​ 如果JVM检查到原来的线程依然存活,就进一步检查占有线程的调 用堆栈是否通过锁记录持有偏向锁。如果存在锁记录,就表明原来的 线程还在使用偏向锁,发生锁竞争,撤销原来的偏向锁,将偏向锁膨胀(INFLATING)为轻量级锁。

轻量级锁

使用场景:如果一个对象虽然有多线程访问,但多线程访问的时间是错开的(也就是没有竞争),那么可以使用轻量级锁来优化。

轻量级锁的本意是为了减少多线程进入操作系统底层的互斥锁 (Mutex Lock)的概率,并不是要替代操作系统互斥锁。所以,在争 用激烈的场景下,轻量级锁会膨胀为基于操作系统内核互斥锁实现的 重量级锁。

执行过程

(1)在抢锁线程进入临界区之前,如果内置锁 (临界区的同步对象)没有被锁定,JVM首先将在抢锁线程的栈帧中建 立一个锁记录(Lock Record),用于存储对象目前Mark Word的拷 贝,这时的线程堆栈与内置锁对象头大致如图所示,

在这里插入图片描述

(2)然后抢锁线程将使用CAS自旋操作,尝试将内置锁对象头的Mark Word的ptr_to_lock_record(锁记录指针)更新为抢锁线程栈帧中锁 记录的地址,如果这个更新执行成功了,这个线程就拥有了这个对象锁。然后JVM将Mark Word中的lock标记位改为00(轻量级锁标志), 即表示该对象处于轻量级锁状态。

(3)抢锁成功之后,JVM会将Mark Word 中原来的锁对象信息(如哈希码等)保存在抢锁线程锁记录的 Displaced Mark Word(可以理解为放错地方的Mark Word)字段中, 再将抢锁线程中锁记录的owner指针指向锁对象。

在轻量级锁抢占成功之后,锁记录和对象头的状态如图所示,

在这里插入图片描述

如果cas失败,有两种情况:

  1. 如果是其他线程已经持有了该Object的轻量级锁,这时表明有就竞争,进入锁膨胀过程
  2. 如果是自己执行了 synchronized 锁重入,那么再添加一条 Lock Record 作为重入的计数

当退出 synchronized 代码块(解锁时)如果有取值为null的锁记录,表示有重入,这时重置锁记录,表示重入计数减一。

当退出 synchronized 代码块(解锁时)锁记录的值不为null,这时使用 cas 将 Mark Word 的值恢复给对象头,成功则解锁成功,失败说明轻量级锁已经进行了锁膨胀或者已经升级为重量级锁,进入重量级锁的解锁流程。

轻量级锁的分类

轻量级锁主要有两种:普通自旋锁和自适应自旋锁。

普通自旋锁

​ 普通自旋锁指当有线程来竞争锁时,抢锁线程会在原 地循环等待,而不是被阻塞,直到那个占有锁的线程释放锁之后,这 个抢锁线程才可以获得锁。

​ 锁在原地循环等待的时候是会消耗CPU的,就相当于在执行一个 什么也不干的空循环。所以轻量级锁适用于临界区代码耗时很短的场 景,这样线程在原地等待很短的时间就能够获得锁了。默认情况下,自旋的次数为10次,用户可以通过XX:PreBlockSpin选项来进行更改。

自适应自旋锁

​ 自适应自旋锁就是等待线程空循环的自旋次数并非是固定 的,而是会动态地根据实际情况来改变自旋等待的次数,自旋次数由 前一次在同一个锁上的自旋时间及锁的拥有者的状态来决定。

  • 如果抢锁线程在同一个锁对象上之前成功获得过锁,JVM就 会认为这次自旋很有可能再次成功,因此允许自旋等待持续相对更长 的时间。
  • 如果对于某个锁,抢锁线程很少成功获得过,那么JVM将可 能减少自旋时间甚至省略自旋过程,以避免浪费处理器资源。

JDK 1.6的轻量级锁使用的是普通自旋锁,且需要使用XX:+UseSpinning选项手工开启。JDK 1.7后,轻量级锁使用自适应自旋 锁,JVM启动时自动开启,且自旋时间由JVM自动控制。

重量级锁

​ JVM中每个对象都会有一个监视器,监视器和对象一起创建、销 毁。监视器相当于一个用来监视这些线程进入的特殊房间,其义务是 保证(同一时间)只有一个线程可以访问被保护的临界区代码块。本质上,监视器是一种同步工具,也可以说是一种同步机制,监听器主要有两个特点。

  • 同步。监视器所保护的临界区代码是互斥地执行的。一个监 视器是一个运行许可,任一线程进入临界区代码都需要获得这个许 可,离开时把许可归还。
  • 协作。监视器提供Signal机制,允许正持有许可的线程暂时 放弃许可进入阻塞等待状态,等待其他线程发送Signal去唤醒;其他 拥有许可的线程可以发送Signal,唤醒正在阻塞等待的线程,让它可 以重新获得许可并启动执行。

在Hotspot虚拟机中,监视器是由C++类ObjectMonitor实现的,ObjectMonitor的Owner(_owner)、WaitSet(_WaitSet)、 Cxq(_cxq)、EntryList(_EntryList)这几个属性比较关键。ObjectMonitor的WaitSet、Cxq、EntryList这三个队列存放抢夺重量 级锁的线程,而ObjectMonitor的Owner所指向的线程即为获得锁的线 程。

  • Cxq:竞争队列(Contention Queue),所有请求锁的线程 首先被放在这个竞争队列中。
  • EntryList:Cxq中那些有资格成为候选资源的线程被移动到 EntryList中。
  • WaitSet:某个拥有ObjectMonitor的线程在调用 Object.wait()方法之后将被阻塞,然后该线程将被放置在WaitSet链 表中。

ObjectMonitor的内部抢锁过程如图所示:

在这里插入图片描述

(1) Cxq

​ Cxq并不是一个真正的队列,而是一个由Node及其next指针逻辑构成的虚拟队列。每 次新加入Node会在Cxq的队头进行,通过CAS改变第一个节点的指针为 新增节点,同时设置新增节点的next指向后续节点;从Cxq取得元素 时,会从队尾获取。Cxq结构是一个无锁结构。

​ 在线程进入Cxq前,抢锁线程会先尝试通过CAS自旋获取锁,如果 获取不到,就进入Cxq队列,这明显对于已经进入Cxq队列的线程是不 公平的。因此,synchronized同步块所使用的重量级锁是不公平锁。

(2) EntryList

​ EntryList与Cxq在逻辑上都属于等待队列。Cxq会被线程并发访 问,为了降低对Cxq队尾的争用,而建立EntryList。在Owner线程释放 锁时,JVM会从Cxq中迁移线程到EntryList,并会指定EntryList中的 某个线程(一般为Head)为OnDeck Thread(Ready Thread)。 EntryList中的线程作为候选竞争线程而存在。

(3) OnDeck Thread与Owner Thread

​ JVM不直接把锁传递给Owner Thread,而是把锁竞争的权利交给 OnDeck Thread,OnDeck需要重新竞争锁。这样虽然牺牲了一些公平 性,但是能极大地提升系统的吞吐量,在JVM中,也把这种选择行为称 为“竞争切换”。

​ OnDeck Thread获取到锁资源后会变为Owner Thread。无法获得锁 的OnDeck Thread则会依然留在EntryList中,考虑到公平性,OnDeck Thread在EntryList中的位置不发生变化(依然在队头)。

​ 在OnDeck Thread成为Owner的过程中,还有一个不公平的事情, 就是后来的新抢锁线程可能直接通过CAS自旋成为Owner而抢到锁。

(4) WaitSet

​ 如果Owner线程被Object.wait()方法阻塞,就转移到WaitSet队列 中,直到某个时刻通过Object.notify()或者Object.notifyAll()唤 醒,该线程就会重新进入EntryList中。

偏向锁、轻量级锁与重量级锁的对比

synchronized的执行过程:

  1. 线程抢锁时,JVM首先检测内置锁对象Mark Word中的 biased_lock(偏向锁标识)是否设置成1,lock(锁标志位)是否为 01,如果都满足,确认内置锁对象为可偏向状态。
  2. 在内置锁对象确认为可偏向状态之后,JVM检查Mark Word中 的线程ID是否为抢锁线程ID,如果是,就表示抢锁线程处于偏向锁状 态,抢锁线程快速获得锁,开始执行临界区代码。
  3. 如果Mark Word中的线程ID并未指向抢锁线程,就通过CAS操 作竞争锁。如果竞争成功,就将Mark Word中的线程ID设置为抢锁线 程,偏向标志位设置为1,锁标志位设置为01,然后执行临界区代码, 此时内置锁对象处于偏向锁状态。
  4. 如果CAS操作竞争失败,就说明发生了竞争,撤销偏向锁, 进而升级为轻量级锁。
  5. JVM使用CAS将锁对象的Mark Word替换为抢锁线程的锁记录 指针,如果成功,抢锁线程就获得锁。如果替换失败,就表示其他线 程竞争锁,JVM尝试使用CAS自旋替换抢锁线程的锁记录指针,如果自 旋成功(抢锁成功),那么锁对象依然处于轻量级锁状态。
  6. 如果JVM的CAS替换锁记录指针自旋失败,轻量级锁就膨胀为 重量级锁,后面等待锁的线程也要进入阻塞状态。

总体来说,偏向锁是在没有发生锁争用的情况下使用的;一旦有 了第二个线程争用锁,偏向锁就会升级为轻量级锁;如果锁争用很激 烈,轻量级锁的CAS自旋到达阈值后,轻量级锁就会升级为重量级锁。

三种内置锁的对比如图:

在这里插入图片描述

http://www.ritt.cn/news/1665.html

相关文章:

  • 数据交易网站源码宁波seo服务快速推广
  • 电子商务网站建设的相关流程技术培训机构
  • 苏州推广关键词优化岳阳seo
  • 迅雷网站做爰视频快速网站排名提升工具
  • asp.net动态网站成品社交网络的推广方法
  • 上海建智咨询培训网站百度有哪些app产品
  • 做外汇需要了解的网站能让手机流畅到爆的软件
  • 付公司网站费用怎么做分录昆明seo关键词
  • 12380网站开发电商平台推广
  • 温州网站建设 seo怎么宣传自己的店铺
  • app制作软件平台搜索引擎优化名词解释
  • 东莞网站建设哪家公司好郑州网络推广报价
  • 网站退出率是什么意思站长推荐入口自动跳转
  • 网站备案管理系统登录不上去百色seo关键词优化公司
  • dede网站名称不能中文360免费建站官网
  • 吉林天宇建设集团网站seo范畴有哪些
  • 做近代史纲要题的网站宁波网站建设
  • 做网站商城怎么样成都比较靠谱的seo
  • 企业网站建立的失败案例网店运营推广中级实训
  • 江宁网站建设网络营销与传统营销的区别
  • 娄底营销型网站建设杭州seo顾问
  • 商城网站建设源码发布平台
  • 做dnf辅助网站云南省最新疫情情况
  • 网站建设灯湖南长沙疫情最新情况
  • 惠来做网站百度广告联盟官网
  • 万州网站建设济南seo优化外包服务
  • 专业做网站的页面设计windows优化软件
  • 做网站广告语搜索引擎优化的简写是
  • wordpress文章页调用分类列表seo服务商
  • 镇江手机网站制作企业网站源码