数据库并发锁机制
数据库并发锁机制在如今分布式、高并发、各种负载纵横天下的时代,支持高访问量成为检验一个系统合不合格的重要标准,然而我们除了在运算过程中要求系统更加效率外,在最终的数据存储过程中也希望其能够准确。
并发修改同一记录时为避免更新丢失,要么在应用层加锁,要么在缓存加锁,要么在数据库层使用乐观锁,使用 version 作为更新依据。
悲观锁:正如其名,它指对数据被外界(可能是本机的其他事务,也可能是来自其它服务器的事务处理)的修改持保守态度。在整个数据处理过程中,将数据处于锁定状态。悲观锁大多数情况下依靠数据库的锁机制实现,以保证操作最大程度的独占性。如果加锁的时间过长,其他用户长时间无法访问,影响程序的并发访问性,同时这样对数据库性能开销影响也很大,特别是长事务而言,这样的开销往往无法承受。
乐观锁:分为三个阶段:数据读取、写入校验、数据写入。
假设数据一般情况下不会造成冲突,只有在数据进行提交更新时,才会正式对数据的冲突与否进行检测,如果发现冲突了,则返回错误信息,让用户决定如何去做。fail-fast机制。
小结:
乐观锁和悲观锁之间选择的标准是冲突的频率、严重性。如果冲突较少或者冲突的 ...
JVM系列-第12章-垃圾回收器
垃圾回收器GC 分类与性能指标垃圾回收器概述
垃圾收集器没有在规范中进行过多的规定,可以由不同的厂商、不同版本的JVM来实现。
由于JDK的版本处于高速迭代过程中,因此Java发展至今已经衍生了众多的GC版本。
从不同角度分析垃圾收集器,可以将GC分为不同的类型。
Java不同版本新特性
语法层面:Lambda表达式、switch、自动拆箱装箱、enum、泛型
API层面:Stream API、新的日期时间、Optional、String、集合框架
底层优化:JVM优化、GC的变化、元空间、静态域、字符串常量池等
垃圾回收器分类按线程数分(垃圾回收线程数),可以分为串行垃圾回收器和并行垃圾回收器。
串行回收指的是在同一时间段内只允许有一个CPU用于执行垃圾回收操作,此时工作线程被暂停,直至垃圾收集工作结束。
在诸如单CPU处理器或者较小的应用内存等硬件平台不是特别优越的场合,串行回收器的性能表现可以超过并行回收器和并发回收器。所以,串行回收默认被应用在客户端的Client模式下的JVM中
在并发能力比较强的CPU上,并行回收器产生的停顿时间要短于串行回收器
和串行 ...
JVM系列-第11章-垃圾回收相关概念
垃圾回收相关概念System.gc() 的理解
在默认情况下,通过System.gc()者Runtime.getRuntime().gc() 的调用,会显式触发Full GC,同时对老年代和新生代进行回收,尝试释放被丢弃对象占用的内存。
然而System.gc()调用附带一个免责声明,无法保证对垃圾收集器的调用(不能确保立即生效)
JVM实现者可以通过System.gc() 调用来决定JVM的GC行为。而一般情况下,垃圾回收应该是自动进行的,无须手动触发,否则就太过于麻烦了。在一些特殊情况下,如我们正在编写一个性能基准,我们可以在运行之间调用System.gc()
代码示例:手动执行 GC 操作
123456789101112131415public class SystemGCTest { public static void main(String[] args) { new SystemGCTest(); System.gc();//提醒jvm的垃圾回收器执行gc,但是不确定是否马上执行gc //与Run ...
JVM系列-第10章-垃圾回收概述和相关算法
垃圾回收概述
Java 和 C++语言的区别,就在于垃圾收集技术和内存动态分配上,C++语言没有垃圾收集技术,需要程序员手动的收集。
垃圾收集,不是Java语言的伴生产物。早在1960年,第一门开始使用内存动态分配和垃圾收集技术的Lisp语言诞生。
关于垃圾收集有三个经典问题:
哪些内存需要回收?
什么时候回收?
如何回收?
垃圾收集机制是Java的招牌能力,极大地提高了开发效率。如今,垃圾收集几乎成为现代语言的标配,即使经过如此长时间的发展,Java的垃圾收集机制仍然在不断的演进中,不同大小的设备、不同特征的应用场景,对垃圾收集提出了新的挑战,这当然也是面试的热点。
大厂面试题蚂蚁金服
你知道哪几种垃圾回收器,各自的优缺点,重点讲一下CMS和G1?
JVM GC算法有哪些,目前的JDK版本采用什么回收算法?
G1回收器讲下回收过程GC是什么?为什么要有GC?
GC的两种判定方法?CMS收集器与G1收集器的特点
百度
说一下GC算法,分代回收说下
垃圾收集策略和算法
天猫
JVM GC原理,JVM怎么回收内存
CMS特点,垃圾回收算法有哪些?各自的优缺点,他们共同 ...
JVM系列-第9章-StringTable(字符串常量池)
StringTable(字符串常量池)String的基本特性
String:字符串,使用一对 “” 引起来表示
12String s1 = "atguigu" ; // 字面量的定义方式String s2 = new String("hello"); // new 对象的方式
String被声明为final的,不可被继承
String实现了Serializable接口:表示字符串是支持序列化的。实现了Comparable接口:表示String可以比较大小
String在jdk8及以前内部定义了final char value[]用于存储字符串数据。JDK9时改为byte[]
为什么 JDK9 改变了 String 的结构
官方文档:http://openjdk.java.net/jeps/254
为什么改为 byte[] 存储?
String类的当前实现将字符存储在char数组中,每个字符使用两个字节(16位)。
从许多不同的应用程序收集的数据表明,字符串是堆使用的主要组成部分,而且大多数字符串对象只包含 ...
JVM系列-第8章-执行引擎
执行引擎执行引擎概述
执行引擎概述
执行引擎是Java虚拟机核心的组成部分之一。
“虚拟机”是一个相对于“物理机”的概念,这两种机器都有代码执行能力,其区别是物理机的执行引擎是直接建立在处理器、缓存、指令集和操作系统层面上的,而虚拟机的执行引擎则是由软件自行实现的,因此可以不受物理条件制约地定制指令集与执行引擎的结构体系,能够执行那些不被硬件直接支持的指令集格式。
JVM的主要任务是负责装载字节码到其内部,但字节码并不能够直接运行在操作系统之上,因为字节码指令并非等价于本地机器指令,它内部包含的仅仅只是一些能够被JVM所识别的字节码指令、符号表,以及其他辅助信息。
那么,如果想要让一个Java程序运行起来,执行引擎(Execution Engine)的任务就是将字节码指令解释/编译为对应平台上的本地机器指令才可以。简单来说,JVM中的执行引擎充当了将高级语言翻译为机器语言的译者。
1、前端编译:从Java程序员-字节码文件的这个过程叫前端编译
2、执行引擎这里有两种行为:一种是解释执行,一种是编译执行(这里的是后端编译)。
执行引擎工作过程
执行引擎工作过程
执行 ...
JVM系列-第7章-对象的实例化内存布局与访问定位
对象的实例化内存布局与访问定位对象的实例化大厂面试题
美团:
对象在JVM中是怎么存储的?
对象头信息里面有哪些东西?
蚂蚁金服:
二面:java对象头里有什么
对象创建的方式
new:最常见的方式、单例类中调用getInstance的静态类方法,XXXFactory的静态方法
Class的newInstance方法:在JDK9里面被标记为过时的方法,因为只能调用空参构造器,并且权限必须为 public
Constructor的newInstance(Xxxx):反射的方式,可以调用空参的,或者带参的构造器
使用clone():不调用任何的构造器,要求当前的类需要实现Cloneable接口中的clone方法
使用序列化:从文件中,从网络中获取一个对象的二进制流,序列化一般用于Socket的网络传输
第三方库 Objenesis
对象创建的步骤
从字节码看待对象的创建过程
12345public class ObjectTest { public static void main(String[] args) { Object obj ...
JVM系列-第6章-方法区
方法区栈、堆、方法区的交互关系从线程共享与否的角度来看
ThreadLocal:如何保证多个线程在并发环境下的安全性?典型场景就是数据库连接管理,以及会话管理。
栈、堆、方法区的交互关系
下面涉及了对象的访问定位
Person 类的 .class 信息存放在方法区中
person 变量存放在 Java 栈的局部变量表中
真正的 person 对象存放在 Java 堆中
在 person 对象中,有个指针指向方法区中的 person 类型数据,表明这个 person 对象是用方法区中的 Person 类 new 出来的
方法区的理解
官方文档:https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5.4
方法区在哪里?
《Java虚拟机规范》中明确说明:尽管所有的方法区在逻辑上是属于堆的一部分,但一些简单的实现可能不会选择去进行垃圾收集或者进行压缩。但对于HotSpotJVM而言,方法区还有一个别名叫做Non-Heap(非堆),目的就是要和堆分开。
所以,方法区可以看作是一块独立于Java ...
JVM系列-第5章-堆
堆堆的核心概述堆与进程
堆针对一个JVM进程来说是唯一的。也就是一个进程只有一个JVM实例,一个JVM实例中就有一个运行时数据区,一个运行时数据区只有一个堆和一个方法区。
但是进程包含多个线程,他们是共享同一堆空间的。
一个JVM实例只存在一个堆内存,堆也是Java内存管理的核心区域。
Java堆区在JVM启动的时候即被创建,其空间大小也就确定了,堆是JVM管理的最大一块内存空间,并且堆内存的大小是可以调节的。
《Java虚拟机规范》规定,堆可以处于物理上不连续的内存空间中,但在逻辑上它应该被视为连续的。
所有的线程共享Java堆,在这里还可以划分线程私有的缓冲区(Thread Local Allocation Buffer,TLAB)。
《Java虚拟机规范》中对Java堆的描述是:所有的对象实例以及数组都应当在运行时分配在堆上。(The heap is the run-time data area from which memory for all class instances and arrays is allocated)
从实际使用角度看:“几乎”所有 ...
JVM系列-第4章-虚拟机栈
虚拟机栈简介虚拟机栈的出现背景
由于跨平台性的设计,Java的指令都是根据栈来设计的。不同平台CPU架构不同,所以不能设计为基于寄存器的【如果设计成基于寄存器的,耦合度高,性能会有所提升,因为可以对具体的CPU架构进行优化,但是跨平台性大大降低】。
优点是跨平台,指令集小,编译器容易实现,缺点是性能下降,实现同样的功能需要更多的指令。
内存中的栈与堆
首先栈是运行时的单位,而堆是存储的单位。
即:栈解决程序的运行问题,即程序如何执行,或者说如何处理数据。堆解决的是数据存储的问题,即数据怎么放,放哪里
虚拟机栈基本内容
Java虚拟机栈是什么?
Java虚拟机栈(Java Virtual Machine Stack),早期也叫Java栈。每个线程在创建时都会创建一个虚拟机栈,其内部保存一个个的栈帧(Stack Frame),对应着一次次的Java方法调用,栈是线程私有的
1234567891011121314151617181920public class StackTest { public static void main(String[] args) ...