自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(57)
  • 收藏
  • 关注

原创 操作系统是如何实现锁的?

首先要搞清楚一个概念,在硬件层面,CPU 提供了原子操作、关中断、锁内存总线的机制;OS 基于这几个 CPU 硬件机制,就能够实现锁;再基于锁,就能够实现各种各样的同步机制(信号量、消息、Barrier 等)在多线程编程中,为了保证数据操作的一致性,操作系统引入了锁机制,用于保证临界区代码的安全。通过锁机制,能够保证在多核多线程环境中,在某一个时间点上,只能有一个线程进入临界区代码,从而保证临界区中操作数据的一致性。锁机制的一个特点是它的同步原语都是原子操作操作系统之所以能构建锁之类的同步原语,是因为硬件已

2023-04-07 11:10:19 818

原创 系统调用的基本概念

我们运行的程序基本都是运行在用户态,如果需要调用操作系统提供的系统态级别的子功能,就需要系统调用。也就是说在我们运行的用户程序中,凡是与系统态级别的资源有关的操作(如文件管理、进程控制、内存管理等),都必须通过系统调用方式向操作系统提出服务请求,并由操作系统代为完成。

2023-04-07 10:54:12 247

原创 用户态、内核态的基本概念及切换方式

用户态:用户态运行的进程可以直接读取用户程序的数据内核态:内核态运行的进程或程序几乎可以访问计算机的任何资源,不受限制两者最重要的差别就在于特权级的不同,即权力的不同。运行在用户态下的程序不能直接访问操作系统内核数据结构和程序。当我们在系统中执行一个程序时,大部分时间是运行在用户态下的,在其需要操作系统帮助完成某些它没有权力和能力完成的工作时就会切换到内核态1. 系统调用:这是用户态进程主动要求切换到内核态的一种方式,用户态进程通过系统调用申请使用操作系统提供的服务程序完成工作。而系统调用的机制其核心还是使

2023-04-07 10:50:00 1222

原创 内存管理机制、分页和分段共同点和区别、基本分页储存管理方式、基本分段储存管理方式、段页式内存管理

内存的内部是由各种 IC 电路组成的,它的种类很庞大,但是其主要分为三种存储器:操作系统的内存管理主要负责内存的分配与回收(malloc 函数:申请内存,free 函数:释放内存),另外地址转换也就是将逻辑地址转换成相应的物理地址等功能也是操作系统内存管理做的事情连续分配管理方式:连续分配管理方式是指为一个用户程序分配一个连续的内存空间,常见的如块式管理1. 页式管理 :把主存分为大小相等且固定的一页一页的形式,页较小,相对相比于块式管理的划分力度更大,提高了内存利用率,减少了碎片。页式管理通过

2023-04-07 10:46:41 588

原创 CPU的基本概念、CPU调度、CPU常见考点

1. CPU(中央处理器)2. 进程是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。3. 资源分配的最小单位是进程,而 CPU 调度的最小单位是时间片。4. 系统为进程分配资源,不对线程分配资源1. 高级调度(作业调度):2. 中级调度:3. 低级调度(进程调度/线程调度)

2023-04-07 09:52:01 567

原创 操作系统的基本概念

1. 并发:同一段时间内多个程序执行。2. 共享:系统中的资源可以被内存中多个并发执行的进线程共同使用。3. 异步:系统中的进程是以走走停停的方式执行的,且以一种不可预知的速度推进4. 虚拟 :通过时分复用(如分时系统)以及空分复用(如虚拟内存)技术实现把一个物理实体虚拟为多个。

2023-04-07 09:38:29 76

原创 操作系统中的堆栈

操作系统的堆和栈是指对内存进行操作和管理的一些方式这和数据结构中的堆和栈是有区别的。1. 一般由程序员分配释放,并指明大小,堆被程序申请使用的内存在被主动释放前一直有效。堆需要由由程序员手动释放,不及时回收容易产生内存泄露。程序结束时可能由操作系统回收。2. 栈是存放在一级缓存中的,而堆则是存放在二级缓存中的,堆的生命周期由虚拟机的垃圾回收算法来决定(并不是一旦成为孤儿对象就能被回收),所以调用这些对象的速度要相对来得低一些,故堆的速度慢于栈的速度3. 与数据结构中的堆是不同的,分配方式类似于链

2023-04-07 09:29:20 741

原创 死锁的基本概念、死锁的触发条件、如何解决死锁问题、如何查看死锁?

死锁是指多个进程在运行过程中因争夺资源而造成的一种僵局,当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进。

2023-04-07 09:22:16 291

原创 leetcode713

以当前元素(即right指向的元素)为尾缀的元素有多少个,一共有right-left+1个。

2023-04-06 11:30:15 49

原创 并查集(leetcode547、leetcode990题解)

【代码实现】并查集(leetcode547、leetcode990题解)

2023-04-06 11:26:26 51

原创 如何实现数状数组?

【代码】如何实现数状数组?

2023-04-06 11:14:52 45

原创 KMP算法的实现

首先匹配串会检查之前已经匹配成功的部分中里是否存在相同的「前缀」和「后缀」。

2023-04-06 11:09:25 44

原创 二分查找查找一个大于等于target的数、第一个等于target的元素、最后一个等于target的元素、一个数组里面最接近的target的数、二分查找有序矩阵为target的元素

一个数组里面最接近的target的数,While循环必须是left

2023-04-06 11:02:09 272

原创 BeanFactory与ApplicationContex的区别

BeanFactory与ApplicationContext的区别

2023-04-06 10:39:18 50

原创 快速排序、双路快排、插入排序、冒泡排序、选择排序、堆排序、归并排序、基数排序

本文主要讲诉了常见的排序算法,还有排序算法的一些升级版,例如双路快排等

2023-04-05 22:55:24 63

原创 链表反转的三种方法

本文主要对链表反转的三种方法进行了实现,分别使用了迭代,新建一条链表进行迭代,还有使用递归进行反转。

2023-04-05 22:47:16 52

原创 leetcode742

本文主要讲诉了leetcode中使用dijkstra算法来求最短路径的问题

2023-04-05 22:40:20 43

原创 图的BFS与DFS

本文主要讲诉了图的BFS与DFS的具体代码实现过程

2023-04-05 22:34:44 54

原创 Spring源码全体系流程图

讲诉Spring xml文件得解析,生成对应的beanDefinition存入BeanFactory,接下来还包括Bean的实例化和初始化阶段各个重要接口的调用

2023-04-05 22:20:05 230 2

原创 Netty底层剖析——零拷贝

零拷贝:不是说没有拷贝,而是拷贝的过程不需要通过CPU来搬运数据,所有的数据都是通过DMA来传输,零拷贝技术的文件传输方式相比传统文件传输的方式,减少了 2 次上下文切换和数据拷贝次数,只需要 2 次上下文切换和数据拷贝次数,就可以完成文件的传输,而且 2 次的数据拷贝过程,都不需要通过 CPU,2 次都是由 DMA 来搬运。大文件不应该使用零拷贝。 1、Netty的接受和发送ByteBuffer采用DIRECT BUFFERS,使用堆外直接内存进行Socket读写,不需要进行字节缓冲区的二

2022-07-26 11:44:43 1006

原创 Redis底层剖析——AOF

AOF重写缓冲区用来解决服务器当前的数据状态和重写后的AOF文件所保存的数据库状态不一致的问题(子进程在进行AOF重写期间,服务器还需要继续处理命令请求,而新的命令可能会对现有的数据库状态进行修改,从而使得服务器当前的数据库状态和重写后的AOF文件所保存的数据库状态不一致),这个缓冲区在服务器创建子进程后开始使用。被写入AOF文件的所有命令都是以Redis的命令请求协议格式保存的,因为Redis的命令请求协议是纯文本格式。因为AOF文件的内容会越来越多,为了减少AOF文件越来越大出现了AOF文件重写。...

2022-07-26 11:44:02 172

原创 Redis底层剖析——对象篇

字符串对象的编码可以是int、raw、embstr如果一个字符串对象保存的是整数值,并且这个整数值可以用long类型来表示,那么字符串对象会将整数值保存再字符串对象结构的ptr属性里面(将void*转换为long)...

2022-07-26 11:43:44 93

原创 ConcurrentPrograming——轻量级与偏向锁之间的转换

下面例子(取消了偏向锁延迟)第一个输出可以看出一开始后3位为101表明默认开启了偏向锁此时,且此时没有线程id、分代年龄等信息,第二条输出可以看到后三位仍是101说明处于偏向锁状态,且前面不为空,此时有了线程id、分代年龄等信息,第三条输出,此时还是101(因为默认101),解锁后前面的信息仍不为空,表明偏向锁的特性,线程使用完偏向锁后,偏向锁会记录线程id等信息,即使是解锁之后,表明此对象为此id的线程专属,正常情况下其他锁释放后,前面的内容会清空而偏向锁不会,还记录着线程的ID表明偏向的特性。...

2022-07-26 11:43:18 203

原创 ConcurrentPrograming——Synochronized

1、如果竞争锁失败会处于Blocked状态,处于Synochronized中的线程,即使持有锁时间片用完,其他想持有锁对象也获得不到锁的使用权(因为竞争失败处于Blocked状态不会被CPU分配时间片),此时cpu只会把时间片分配给持有锁对象让它继续执行。重量级锁竞争的时候,使用自旋进行优化,先不进入阻塞,而是尝试获得锁,如果在尝试获得锁的同时,其他线程刚好释放了对锁的使用权,则不用进入EntryList中进行阻塞,阻塞意味着会进行一次上下文切换,会极大的耗费资源,所以用自旋进行优化。...

2022-07-26 11:42:46 94

原创 Redis底层剖析——文件事件与时间事件

负责监听多个套接字,并向文件事件分派器传送那些产生了事件的套接字,尽管多个文件事件可能会并发出现,但I/O多路复用程序总是会将所有产生事件的套接字放到一个队列里面,然后通过这个队列,以有序、同步、每次一个套接字的方式像文件事件分派器传送套接字,在上个套接字产生的事件被处理完,I/O多路复用程序才会继续向文件事件分派下一个套接字。当被监听的套接字准备好执行连接、应答、写入、关闭等操作时,相应的文件事件就会产生,这时文件事件处理器就会调用套接字之前关联好的事件处理器来处理这些事件。...

2022-07-26 11:42:23 228

原创 Redis底层剖析——主从复制

Sentinel通过主服务器发送INFO命令来获得主服务器属下所有从服务器的地址信息,并未这些从服务器创建相应的实例结构,Sentinel以每十秒一次的频率向被监视的主服务器和从服务器发送Info命令,当主服务器处于下线状态,或者Sentinel正在对主服务器进行故障扫描室,频率会改为一秒一次。可以监视多个嘱咐其或者其下的从服务器,可以在被监视的主服务器下线,自动将下线主服务器属下的某个从服务器升级为新的主服务器,代替旧的主服务器。1、主服务器的复制偏移量和从服务器的复制偏移量。3、服务器的运行ID。...

2022-07-26 11:41:59 90

原创 Redis底层剖析——Redis底层的数据结构

假设在一个压缩列表中,有多个连续的、长度介于250字节到253字节之间的节点e1-en,当插入新节点时,就会导致e1放不下需要额外扩张空间保存前一个节点的长度值,扩展后这个节点又大于了255字节,下下节点又进行空间重分配操作,造成连锁更新。压缩列表是列表键和哈希键的底层实现之一,当一个列表键只包含少量列表项,并且每个列表项要么就是最小整数值,要么就是长度比较短的字符串,那么Redis就会使用压缩列表来做列表键的底层实现。2、尽量的节约内存,确保升级操作只会在有需要的时候进行,可以尽量节省内存。......

2022-07-26 11:41:34 127

原创 ConcurrentPrograming——重量级锁与轻量级锁之间的转换

Thread-1发现Object状态为00即有线程已对此对象加锁,Thread-1加轻量级锁失败,会进行锁膨胀,线程一会为Object申请一个Monitor锁(重量级锁),让Object中MarkWord指向Monitor的地址,然后Thread-1进入Monitor中的EntryList中阻塞,此时持有锁的线程锁级别升级,成为Monitor的Owner。如果尝试加轻量级锁的过程中,CAS操作无法成功,表明可能有其他线程为这个对象加上了锁,这时会进行锁膨胀,将轻量级锁变成重量级锁。如果成功,表明解锁成功。.

2022-07-16 21:04:41 296

原创 ConcurrentPrograming——线程状态

等操作完成,会由操作系统唤醒阻塞的线程,变成可运行状态,注意阻塞状态不会变成运行状态,只会变成可运行状态,重新竞争CPU的使用权,等待CPU分配时间片。JAVA中的三种阻塞状态Blocked、Waiting、Timed_Waiting也是调度器不会给其分到时间片,放弃时间片的使用,调度器也不会调用它们。调用了阻塞API,如BIO读写文件,此时会让出CPU,将导致上下文切换,进入阻塞状态。操作执行一些阻塞API时,如读取文件时陷入的阻塞状态,不会分到CPU的时间片。包括运行状态、可运行状态、阻塞状态。...

2022-07-16 21:04:10 93

原创 ConcurrentPrograming——JMM

即Java内存模型主存所有线程都共享的数据(静态变量、成员变量)工作内存每个线程私有的(对应局部变量)可见性由JVM缓存优化引起有序性由JVM指令重排序优化引起读屏障能保证之后的读能读到最新的结果,但不能保证读跑到前面去,如下图,t1线程先读了,任会发生指令交错。有序性也是保证自己的线程内的相关代码不被重排序。httpshttpshttpshttps。...

2022-07-16 21:03:23 39

原创 ConcurrentPrograming——ReentrantLock源码篇

现正的节点指向Thread-1的结点,此时会把,原来的头结点断开(可以被垃圾回收处理点),把Thread-1所在的Node清空,让Thread-1原来所在的节点为头结点。下图中的state为1表示获得了锁,state为-1表示当下一个节点进入阻塞队列时有义务去唤醒在阻塞中状态为0的节点,正常状态下为0;进入acquire中又一次执行失败,因为state一直是1,结果任然失败,接着就进入addWaiter中的逻辑,构造Node队列。Thread-0释放锁,进入图一tryRelease流程,如果成功。...

2022-07-16 21:03:03 53

原创 ConcurrentPrograming——基本概念

多核CPU才能实现并行,单核CPU执行并行操作时仍是轮流串行执行(并发),单核CPU执行多线程只是能够让不同的线程轮流使用CPU,不至于一个线程总占用CPU,别的线程没办法干活。上下文切换(从使用CPU到不使用CPU)当CPU处理线程或进程时,任务调度器给每个线程分配时间片,时间片用完会进入阻塞状态,这是会切换其他线程或进程工作叫作上下文切换。发生上下文切换,操作系统要保存当前线程的状态(包括程序计数器、虚拟机栈、栈帧中的信息),并恢复另一个线程的状态(类似于程序计数器)频繁的上下文切换会影响性能。...

2022-07-16 21:02:41 45

原创 ConcurrentPrograming——ConcurrentHashMap

以上内容为个人总结以及网上学习视频总结出来的比较,目的是为了方便加深大家对ConcurrentHashMap的理解,图片若有侵权,必删。httpshttpshttpshttpshttpshttpshttpshttpshttpshttpshttpshttpshttpshttpshttpshttpshttpshttpshttpshttpshttpshttpshttpshttpshttpshttpshttpshttpshttpshttpshttps。......

2022-07-16 21:01:41 51

原创 ConcurrentPrograming——Park&Unpark

每个线程都有自己的一个Parker(背包)对象,由_counter(干粮,调用park时会首先检查干粮是否充足,为0时干粮不充足要进入帐篷休息,为1时干粮充足,不用进入帐篷继续前进,干粮只有一份,由于背包空间有限,也不能累加)、_cond(帐篷)、_mutex三部分组成。(1)用Unsafe.unpark(Thread_0)方法,设置_counter为1(即使已为1,还是设置为1,干粮不会叠加,背包最多存储一份干粮)。(2)检查_counter,本情况为0(干粮不充足),获得_mutex互斥锁。...

2022-07-16 21:01:09 63

原创 ConcurrentPrograming——原理之wait/notify

EntryList处于BLOCKED状态的线程会重新竞争成为新一届Monitor中Owner的主人,新一届Owner的线程主人,可以调用notify/notifyall让处于WaitSet中WAITING状态的线程唤醒,但不意味着可以立即获得锁到的使用权,而是仍需重新进入EntryList中争抢成为Owner的主人,争夺对CPU的使用权。obj.wait()让进入object监视器的线程到waitSet等待,无限的等待直到有线程调用obj.notify()、obj.notifyAll()。...

2022-07-16 21:00:48 51

原创 ConcurrentPrograming——线程池

如上图所示线程池工作流程,当任务来时首先看核心线程数是否足够,如果核心线程数足够,就把任务交给线程池中的核心线程来处理,当核心线程数用完时,如果队列选择的是有界队列,新来的任务被放入阻塞队列中阻塞。单线程线程池的特点当一个线程执行任务时,发生了异常或执行任务失败,此线程失效时,就会创建一个新的线程来顶替它,继续执行任务,但是单线程线程池永远只有一个线程,只有线程失效才会创建新的线程来顶替。2、线程池创建一批线程,让线程重复的利用,减少内存的占用,可以减少线程数量,避免频繁的发生上下文切换。...

2022-07-16 20:59:25 118

原创 ConcurrentPrograming——ReentrantLock

与synochronized一样的是,都支持可重入(指同一个线程如果首次获得了这把锁,那么它是这把锁的拥有者,因此有权利再次获取这把锁,如果是不可重入锁,第二次获得锁时,会把自己也挡住)。可打断(其他线程可以通过调用interrupt打断,终止打断,synochronized和ReentrantLock.lock()都是不可打断的,ReentrantLock的lockInterruptibly()和trylock()方法是支持可打断的,可打断可以防止无限制的等待下去,可以避免死锁)。............

2022-07-16 20:58:46 43

原创 Netty底层剖析——Reactor线程模型

Reactor单线程模型 通过Acceptor类接受客户端的TCP连接请求消息,当链路建立成功之后,通过Dispatch将对应ByteBuffer指派到特定的Handler上派发到指定的Handler上,进行消息解码,用户线程信息编码后通过NIO线程将消息发送给客户端。 缺点:一个NIOO线程同事处理成百上千的链路,性能上无法支撑。 有一个专门的NIO线程-Acceptor线程用于监听服务器,接受客户端的TCP连接请求网络IO操作由一个NIO读写线程池负责,线

2022-07-14 11:53:23 252

原创 Netty底层剖析——Netty的可靠性设计

当读或者写心跳消息发生IO异常的时候,说明链路已经中断,此时需要立即关闭链路,如果是客户端需要重新发起连接,如果是服务端,需要清空缓存的半包消息,等待客户端重连链路。而且需要保证连续N此心跳检测都失败才认定链路已经损坏。 如果链路中断,等待INTERVAL时间后,由客户端发起重连操作,如果重连失败,间隔INTERVAL后再次发起重连,直至重连成功。 为了保证服务端能够有充足的时间释放句柄(一个不变的对象存储着同一个对象随机随时可能会变的地址)资源,在首次断连时客户端需要等待INT

2022-07-14 11:52:48 366

原创 Mysql底层剖析——表锁、行锁、共享锁

默认对update,delete,insert加排他锁,select默认不加锁在手动加共享锁的方式是 select…lock in share mode.手动加排它锁的方式是 select…for update 就是读锁,当前事务加了共享锁以后,其他事务也可以给这条数据加共享锁,但是不能加排它锁,同一个事务的读写是不会互斥的,不同事务的读锁和写锁才会排斥。 就是写锁,update,delete,insert默认都是加写锁,想要申请到写锁,要确保数据没有其他事务的共享锁和排它锁,而

2022-07-14 11:52:16 396

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除