- 博客(29)
- 资源 (3)
- 收藏
- 关注
原创 DateTime和TimeStamp的区别及如何选择
时间范围 1970-01-01 00:00:00” ~ “2038-01-19 03:14:07, 占4个字节, 带时区, 插入null的话会自动插入当前时间。时间范围 1000-01-01 00:00:00~9999-12-31 23:59:59, 占8个字节。DateTime对程序员友好,看起来舒服;TimeStamp适合处理需要跨多个时区的业务。另附一mysql与java对应的类型。
2023-01-12 19:52:46 399 1
原创 什么是Happens-before原则?
这篇文章中,我们提到了为了实现并发编程、提高系统效率,我们引入了缓存、线程、编译优化,也因此引出了可见性、原子性、有序性问题。在并发编程中,我们就需要解决这三个问题。假设由线程A先进入同步代码块,由于规则4,后进入的线程B能够看到A修改后的x值。happens-before的意思是:前面一个操作的结果对后续操作是可见的。:在一个线程中,前面的操作happens-before后面的操作。:主线程A等待子线程B完成,当B完成后,A能看到B的操作。:主线程A启动子线程B后,B能够看到A在启动B前的操作。
2022-10-14 09:24:20 411
原创 什么是可见性、原子性、有序性?
对于同一块内存地址,每个CPU都有自己单独的备份,这样就产生了数据一致性问题. 也就是说线程A修改了共享变量x的值后,线程B不能马上知道.可见性、原子性、有序性是并发编程中经常提到的名词,如果能保证这三个条件,我们的程序就是线程安全的。的检查,A获取到锁后给instance赋值,并且在初始化之前切换到了线程B,B就会返回一个没有初始化过的对象.这三点提高了系统性能,同时也造成了可见性、原子性、有序性三个问题。一个或多个操作在CPU执行的过程中不被中断,这是原子性.。这段双重检查获取单例对象的代码,对于。
2022-10-12 09:45:44 2844
原创 java线程安全的实现
比如hotspot,每个java线程直接映射到一个操作系统原生线程,中间没有额外的间接结构,线程的调度全权交给操作系统去处理(但是虚拟机会给线程设置优先级)。java采用了CAS操作,但是JDK8只有Java类库才可以使用CAS,用户程序是不能用的,我们来看一下AtomicInteger是怎么保证线程安全的。保证线程的安全需要可见性、有序性、原子性,这段代码中通过volatile保证了可见性和有序性,通过CAS保证了原子性。java线程的实现不受虚拟机规范的约束,主流的java虚拟机都采用了。
2022-10-04 09:51:27 407
原创 volatile关键字、java内存模型
java内存模型和cpu内存模型类似。java线程并不会直接读写主内存中存放的共享变量,而是拷贝一个副本在工作内存中,也由此引出了变量可见性的问题(对应cpu缓存不一致问题)volatile实现了变量的可见性和操作的有序性。被volatile关键字修饰的变量,在工作内存中被修改后会立刻写回主内存,并且之后的指令不会被重排序到赋值操作之前。
2022-09-28 11:25:01 158
原创 jvm垃圾收集算法
主流虚拟机的垃圾收集器都遵循了分代收集的策略,一般至少把堆分为两个区域:新生代、老年代。新生代经常会有大量对象死去,每次回收后仅留下一小部分,而老年代正好相反。两个区域适合用不同的算法收集垃圾。
2022-09-21 10:14:47 342
原创 jvm之方法调用过程
方法调用阶段的任务是确定要调用的方法的版本。class文件的编译与其他程序语言不同,它不包含连接步骤。class文件中存储的只是方法的符号引用。需要在类加载阶段(解析)或者运行时(委派)才能确定方法的直接引用。
2022-09-12 12:11:26 546
原创 java虚拟机-双亲委派机制
各种类加载器之间的层次关系被称为类加载器的“双亲委派模型(Parents DelegationModel)”。双亲委派模型要求除了顶层的启动类加载器外,其余的类加载器都应有自己的父类加载器。不过这里类加载器之间的父子关系一般不是以继承(Inheritance)的关系来实现的,而是通常使用组合(Composition)关系来复用父加载器的代码。
2022-09-09 11:24:14 349
原创 缓存--伪共享问题
伪共享问题指两个线程A和B,他们俩写入同一个cache block的不同变量时,会导致另一个cpu核心的缓存失效的问题。解决伪共享有两种办法一般而言,缓存行有64字节,我们知道一个long是8个字节,填充5个long之后,一共就是48个字节。而 Java 中对象头在32位系统下占用8个字节,64位系统下占用16个字节,这样填充5个long型即可填满64字节,也就是一个缓存行。@Contented 注解cocurrenthashmap 中怎...
2022-08-03 10:26:58 1087
原创 CPU的三种工作模式:实模式、保护模式、长模式
cpu的三种工作模式。实模式、保护模式、长模式对应了处理器从16位单任务->32位多任务->64位的发展历史。另外x86CPU在第一次加电时会自动进入实模式,我们需要通过设置CR0寄存器,并且初始化GDT、GDTR等来切换到保护模式或者长模式。...
2022-07-21 16:52:32 5260
原创 TCP为什么要三次握手,握手过程中丢包会怎么样?
接上一篇文章 TCP建立连接的过程。@[TOPIC]TCP建立连接需要三次握手是我们都知道的,那么为什么要是三次握手,而不是一次、两次或者四次、五次、六次呢?为什么是三次握手根据 RFC793 ,三次握手的目的是为了旧的连接请求造成混乱。The principle reason for the three-way handshake is to prevent old duplicate connection initiations from causing confusion.....
2022-03-15 16:40:24 4697
原创 CPU缓存一致性问题
今天复习了下CPU缓存的知识。(๑•̀ㅂ•́)و✧文章目录数据写入内存的两种方式缓存一致性问题总线嗅探MESI协议伪共享CPU的访问速率要远高于内存的访问速率,为了减少内存访问次数,提高计算机系统效率,CPU中引入了缓存。这是我虚拟机的三级缓存结构。L1d和L1i是一级缓存,他距离cpu核心最近,其中,l1d用来存数据,l1i用来存指令。L1和L1 cache是每个核心独有的缓存,而L3则是多个cpu核心共享的。缓存每次从内存中读取的数据的大小cache line 可以从这里看到,默认是64字节
2022-03-08 15:06:09 1209
原创 TCP建立连接的过程
TCP是面向连接的、可靠的、基于字节流的传输层协议,是TCP/IP协议中最重要的协议之一了。我们都知道TCP通过三次握手建立连接,那么每一次握手的作用、为什么要三次握手、如果某次握手丢包会发生什么呢?文章目录第一次握手ISN第二次握手第三次握手为什么是三次握手首先看一下TCP首部:在建立TCP连接的过程中,我们主要关注序号、确认号、ACK和SYN位。这张图是三次握手握手过程中SYN、ACK以及序号确认号的值。第一次握手首先我们来看看客户端发送第一次握手的包时都做了什么:可以看到,6个控制
2022-02-27 16:11:44 3683
原创 jvm之方法区
方法区主要是存储类信息、常量、静态变量的地方,也叫非堆。首先看一下官方文档对方法区的描述:The Java Virtual Machine has a method area that is shared among all Java Virtual Machine threads. The method area is analogous to the storage area for compiled code of a conventional language or analogous to t
2022-01-11 17:19:23 298
原创 jvm之逃逸分析
逃逸分析是指分析一个变量的作用域,看这个变量会不会逃逸到方法外,如果不会的话,则可以对这个变量进行一些优化。《深入理解java虚拟机》中是这样说的:逃逸分析的基本行为就是分析对象动态作用域:当一个对象在方法中被定义后,他可能被外部方法所引用,例如作为调用参数传递到其他的方法中,称为方法逃逸。甚至还有可能被外部线程访问到,譬如复制非类变量或可以在其他线程中访问的实例变量,称为线程逃逸。如果能证明一个对象不会逃逸到方法或线程之外,也就是别的方法或线程无法通过任何途径访问到这个对象,则可能为这个变量进行一些高
2022-01-11 16:26:37 1888
原创 虚拟机栈帧结构
void fun(String a, int b,float v,double z ){ int tmp =0; double f = 1.2; } static void fun2(){ }两个函数对应的结构可以看出来,stack和locals表示的是需要的slot的数量(实例方法的locals还包含一个this的引用),args_size表示的是参数的个数(实例方法加了个一个this,所以fun有5个参数)...
2022-01-11 15:20:07 211
原创 survivor区对象何时进入老年代(深入理解jvm中表述不准确的地方)
我们都知道,survivor区中的对象年龄超过MaxTenuringThreshold后会晋升到老年代,但实际上,只要survivor区中某个年龄段的对象超过一定比例后,大于这个年龄段的对象就会晋升到老年区。对此,《深入理解java虚拟机》中原话是这样说的:如果在Survivor空间中相同年龄所有对象大小的总和大于Survivor空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,无须等到MaxTenuringThreshold中要求的年龄。我在第一次看到这个相同年龄时,就感觉不太对劲。假设下面
2022-01-11 15:08:23 853
原创 i++与 ++i 的区别
首先看一段代码 int i=1,j=2; int a = i++; int b = ++j;上述代码对应的字节码 0 iconst_1 1 istore_1 2 iconst_2 3 istore_2 4 iload_1 5 iinc 1 by 1 8 istore_3 9 iinc 2 by 112 iload_213 istore 4从4、5行号的指令可以看出,i++是先将i从局部变量表取出到操作数栈中,然后将局部变量表中的i加
2022-01-09 11:02:47 276
原创 自定义类加载器
自定义类加载器的作用AppClassLoader只能加载classPath下在class文件,要想从网络输入流中读取加载类的话,需要自定义一个类加载器可以对class文件做一些加解密实现类热部署自定义类加载器一般覆盖findClass方法,覆盖loadClass可以破坏双亲委派 protected Class<?> findClass(String fileName) throws ClassNotFoundException{ try {
2021-12-26 15:52:57 76
原创 clinit方法
当类有字段赋值操作或者静态代码块时,编译后会为这个类生成clinit方法来执行这些语句。clinit方法是被加锁的,同于一时刻只能有一个线程执行某个类的clinit方法。 static class A{ static{//clinit方法 if(true){ System.out.println(Thread.currentThread() + "init Class A"); while .
2021-12-26 14:55:29 559
转载 java字节码指令
Java源码在运行之前都要编译成为字节码格式(如.class文件),然后由ClassLoader将字节码载入运行。在字节码文件中,指令代码只是其中的一部分,里面还记录了字节码文件的编译版本、常量池、访问权限、所有成员变量和成员方法等信息(详见Java字节码格式详解)。本文主要简单介绍不同Java指令的功能以及在代码中如何解析二进制指令。 Java指令是基于栈的体系结构,大部分的指令默认的操作数在栈中。映像中ARM是基于寄存器的操作指令,而x86好像是混合寄存器和存储器的,发现基于栈的操作指令确实
2021-12-11 15:47:42 84
win10/8/7汇编工具masm 有debug,edit,link,masm
2017-09-27
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人