简单了解Semaphore
什么是Semaphore?Semaphore是Java的一个同步类,用于协作多线程,同时也是一个共享锁
Semaphore使用场景限流1234567891011121314151617181920212223242526272829303132public static void main(String[] args) throws IOException { // 限制每次最多只有两个线程执行任务 Semaphore semaphore = new Semaphore(2); for (int i = 0; i < 5; i++) { new MyThread(semaphore).start(); } System.in.read();}static class MyThread extends Thread{ Semaphore semaphore; public MyThread(Semaphore semaphore) { this.sema ...
简单理解什么是进程
什么是进程?进程可以理解为一个正在运行的程序,它有一些比较重要的组成部分:
内存:进程被创建的时候,指令会被加载在内存中、以及一些初始化的数据也会被加载到内存中
寄存器:存放着下一步指令在内存中的位置,以及一些特殊的寄存器比如栈指针、堆指针等等
进程创建的流程其实就是来探究一些如何把磁盘中的程序指令转化成一个进程。
把对应的代码和数据都加载到内存中
给堆(可能分配)、栈(main()函数的栈帧分配)等结构分配内存
初始化任务,如I/O任务的一些文件描述符
执行main()
进程状态那对应的状态大致有5个:创建、就绪、运行、阻塞、结束
对于操作系统如何知道哪些进程是什么状态才能更好的调度进程?
操作系统使用了进程列表的方式存储不同状态的进程。
进程上下文切换对于上下文切换,主要有CPU上下文切换、进程上下文切换、线程上下文切换这3种,大致的意思都差不多。
当进程的时间片用完或者是被阻塞需要放弃时间片又或者是被CPU调度等情况,就需要进行进程上下文切换,这里举例进程A转换到进程B,主要呢就是把进程A的寄存器信息保存到内核栈A中,系统调用完成以后,再将内核栈暂存的寄存器B ...
简单了解CountDownLatch
什么是CountDownLatch?CountDownLatch是Java的一个同步类,用于协作多线程,同时也是一个共享锁
CountDownLatch使用场景等待所有线程完成任务主线程等异步线程
1234567891011121314151617181920212223242526272829public static void main(String[] args) throws InterruptedException { CountDownLatch countDownLatch = new CountDownLatch(3); for (int i = 0; i < 3; i++) { new MyThread(countDownLatch).start(); } countDownLatch.await(); System.out.println("3个线程都完成任务了");}static class MyThread extends Thread{ ...
简单了解TCP/IP四层模型
什么是计算机网络?计算机网络我们可以理解为一个巨大的城市地图,我们想从A地前往B地,其中要走的路、要避开的问题都交给计算机网络解决,直到我们可以正常的到达目的地,那么我们会把其中的过程抽象成一个网络模型,每层负责一个功能。
TCP/IP四层模型图对于传统的OSI七层网络模型,划分的精度太细,不利于实际使用,我们今天来看看TCP/IP四层模型的具体组成:
应用层:主要就是产生原始的数据包
传输层:让接收方知道数据包是给哪个进程的,并且可以选择提供可靠传输
网络层:数据包在不同局域网间传输,直到到达接收方
网络接口层:数据包在局域网内部传输,正确的到达中转站
下层为上层提供服务,上层不需要管下层的具体实现,就比如说应用层只管产生数据,不用管数据是如何到达接收方进程的。
TCP/IP四层模型有什么好处呢?那分层可以理解为拆分,对于拆分到好处我们可以想到将某个方法内部的代码再次封装成一个个的更加小的子方法,那么容易想到:
每个层级的职责会更加的清晰,只负责本层所负责的问题
降低了整体的耦合度,如果我们需要修改某一个层级的实现,不会影响到其它的层级
简单了解什么是AQS
本文基于JDK8
什么是AQS?AQS(AbstractQueuedSynchronizer)抽象队列同步器,一个用来构建锁和同步工具类的框架,比如构建ReentrantLock、ReentrantReadWriteLock这样的锁或是CountDownLatch、CyclicBarrier、Semaphore这样的同步工具类,底层呢是在锁内部或者同步工具类内部自定义同步器Sync,让Sync实现AQS的一些方法完成对资源state的控制效果,从而实现同步。
AQS有两种模式
独占:只有一个线程可以获取到资源
共享:很多线程都可以获取到资源
独占和共享是对于资源来说的,即一个资源能否被多个线程所占有,而公平和非公平是对于线程来说的,即一个新的线程是否需要排队才能获取资源。
AQS的几个重要的成员变量:
Node:同步队列的节点
head、tail:用来维护一个虚拟的双向链表(同步队列,在线程尝试获取资源失败后,会进入同步队列队尾,给前继节点设置一个唤醒信号后,自身进入等待状态(通过LockSupport.park(this)),直到被前继节点唤醒)
state:用来表示资源的情况 ...
简单了解什么是CAS
本文基于JDK8
什么是CAS?CAS(compare and swap),比较与交换,CAS实际上是操作系统底层提供的一个原子指令,对于CAS来说有三个值,V(需要修改的内存的地址)、A(预期初始的值)、B(预期修改后的值),简单来说就是当V位置的数据为A时,我们尝试把它修改为B。当多个线程同时进行修改的时候,只有一个线程可以成功,其它线程都会失败,对于失败的线程区别于锁不会挂起而是会继续尝试修改。
那么CAS在JDK里面的应用呢?像我们熟悉的原子类的一些方法就是和CAS相关
1234public final boolean weakCompareAndSet(int expect, int update) { // valueOffset == V、expect == A、update == B return unsafe.compareAndSwapInt(this, valueOffset, expect, update);}
什么是Unsafe类?Unsafe类有着类似于C语言指针一样可以操作内存的效果,但是如果不正确的使用Unsafe类 ...
mini-spring学习记录
3.8基本的IoC内部构造IoC容器本质上其实是一个Map<beanName, bean>
BeanDefinition:bean的定义信息(包含bean的class类型、构造参数、属性值等信息),我们需要用到BeanDefinition来进行bean的实例化
DefaultListableBeanFactory:常用的一个BeanFactory,本质是一个BeanDefinition的一个注册中心,有一个Map<beanName, beanDefinition>
DefaultSingletonBeanRegistry:单例bean对象的一个缓存池,有三个map,我们一般称为三级缓存
AbstractAutowireCapableBeanFactory:执行bean的生命周期(实例化、初始化等)
12345678//一级缓存private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);// 二级缓存private final Map& ...
简单了解什么是反射
什么是反射?反射是一种能在运行期分析类以及操作Class对象的机制。这里有两个名词待我们了解:
一个是运行期是什么?
在Java项目启动的过程中,程序需要经历两个阶段,首先是编译期(编译器会把.java文件编译成.class文件,然后类加载器会把.class文件加载到内存中)、然后是解释运行期(JVM会把内存中的.class文件翻译成机器语言交给操作系统执行)
一个是分析类是什么?
对于一个类来说,它的元结构信息(构造器、属性、方法等)会被存储在方法区内,同时在堆内存中有一个Class对象与之对应。我们可以通过操作Class对象方式在运行期获取一个类的元结构信息,也可以通过操作Class对象方式获取或者修改类实例化对象的属性、调用其方法或者构造器,同时可以根据需要动态加载一些编译期未知的类(当程序启动,有main方法的类会被加载,同时相关的类会被递归加载,我们可以通过反射延迟加载类,加快程序的启动速度)
反射的优缺点?优点:
可以在运行期获取类信息,无需提前知道类,有助于一些框架通用性的实现
缺点:
反射无法被JIT优化导致操作对象效率较低
破坏了封装特性,可能有安全问题
哪里用到了反 ...
可见性解决方案
volatile是Java的一个关键字,是轻量级的synchronized,用于修饰变量,解决了变量没有可见性和有序性的问题,那什么是变量的可见性和有序性?首先我们先要研究操作系统层面的CPU的缓存一致性问题(对应可见性)和指令优化重排问题(对应有序性),JMM把这些问题封装成了一些关键字(如volatile、synchronized)或者API,我们直接调用就可以解决掉这些问题。
CPU的缓存和主存之间的数据一致性问题首先要谈谈操作系统层面的可见性,也就是CPU和主存之间的缓存一致性的问题,CPU访问数据有局部性,使用缓存可以加快CPU读写数据的速度,但是同时可能造成CPU的缓存和主存之间的数据一致性问题
CPU缓存和主存之间的缓存一致性问题主要有以下原因造成:
CPU之间无法同步:当某个CPU修改了主存的数据之后,其它的CPU是不知道的,还是用的是自己内部过期的缓存
并发问题:当两个或者更多的CPU需要同时读写主存的时候,没有控制并发的机制存在,可能造成读写顺序反过来,导致读取到旧值
基于总线解决CPU缓存一致性只需要在CPU和主存之间加上一条总线,通过总线就可以通知到其它C ...
简单了解Redis底层数据结构
Redis有很多数据类型,这些数据类型对应着很多的数据结构,那么Redis底层是如何存储的呢?
可以看到默认有两个字典(可以理解为两个HashMap),平时只用一个字典进行数据的存储,另一个字典是在rehash的时候会使用到,那么对于数组的每个位置都存储着一个k-v结构,也就是说平时我们set这些操作都是把数据放到数组里面,那每个key和每个value都被当作一个对象存储,也就是图中的 key 对象和 value 对象,这些对象也就是redisObject,有三个属性:
type:表明当前key或者value是什么数据类型
encoding:表明当前数据类型使用了哪种数据结构存储数据(一个数据类型在内存中可以用不同的数据结构存储,这也是Redis高效的原因之一)
ptr:指向底层的数据结构
数据类型
底层数据结构
String
SDS
List
双向链表、压缩列表
Hash
哈希表、压缩列表
Set
整数集合、哈希表
zSet
跳表、压缩列表
SDS
通过len可以O(1)获取字符串长度
通过alloc可以预测是否有空间分配给新修改的value,防 ...