自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(27)
  • 资源 (1)
  • 收藏
  • 关注

原创 jvm八股

双亲委派模型这种工作模式的好处是,具备了一种带有优先级的层次关系,比如java.lang.Object是由启动类加载器加载的,无论哪个类加载器来加载这个类,最终都由启动类加载器加载,那么即使用户自己也编写了一个名为java.lang.Object的类,运行时加载的也是rt.jar里面的那个java.lang.Object,保证了Java类型体系中最基础的行为,避免造成混乱。但是如果不移动对象的话,势必要增加内存管理的复杂度(比如使用空闲链表),降低了分配内存的效率,但不移动对象的话,STW的时间会更短。

2024-03-10 23:20:12 2276 1

原创 Spring循环依赖

回过头来看看为什么要第三级缓存,而且为什么是工厂,而不是直接调用getEarlyBeanReference得到的代理对象。这是因为如果没有循环依赖的话,工厂根本不会被调用,没必要提早生成这个代理对象,只需要按原来的流程,在initializeBean正常生成代理对象即可。然后为什么需要第二级缓存,之前已经说了,存放还没完全创建好的bean呗。

2024-03-02 01:00:24 907

原创 redis八股

做法是:主服务器维护一个固定大小的环形缓冲区,维护一个master_repl_offset记录当前写到的位置,主服务器每次进行写操作时,除了将写操作命令发给从服务器,还会将其写入环形缓冲区中,并推进master_repl_offset,并且由于缓冲区大小有限,最新会覆盖最旧的数据。AOF是记录所有「写操作」的日志。,SDS不仅可以保存字符串还可以保存二进制数据,获取长度的时间复杂度是O(1),SDS的API是安全的,比如拼接字符串不会造成缓冲区溢出,总的来说就是对数组封装,提供一系列方便操作的API。

2024-02-26 22:41:43 2186 2

原创 Striped64源码阅读

Striped64是JUC用于实现Accumulator、Adder高性能计数器的基类,比如LongAdder,在高并发的情况下性能优于AtomicLong,原因是 Striped64使用了分段的技术,减少了高并发下的竞争。Striped64对外的语义是一个数字,在内部将数字的“值”拆成了好几部分:一个base变量和一个 cells数组,当线程尝试修改数字(增减)时,会先尝试对base进行修改,如果成功则退出,如果失败则说明当前存在竞争,会根据线程的哈希值,对cells中的某个元素进行修改。

2024-02-01 16:14:52 827

原创 Semaphore源码阅读

semaphore翻译过来即信号量,对semaphore最直观的解释就是,信号量是一个令牌桶,如果桶里的令牌数>=线程想要获取的令牌数,那么线程就能获取到令牌,然后继续执行,否则就要阻塞等待其他线程将令牌放入桶里,直到桶里令牌数足够,非常简单。不像JUC里的Lock,线程只能释放自己获得的锁,即Lock有owner的概念,不能随便释放其他人的锁。而semaphore中令牌没有owner的概念,任何线程都能随意往桶里放令牌。

2024-01-31 14:26:35 351

原创 CyclicBarrier源码阅读

CountDownLatch:将线程分为执行者和等待者CyclicBarrier:执行者和等待者都是同一批线程如何理解呢,CountDownLatch大家都知道,设置一批工作线程,各自执行完任务就调用CountDownLatch.countDown,表示自己已经执行完任务,该工作线程就可以继续干别的事情了。而CyclicBarrier相当于在CountDownLatch.countDown之后设置了一道屏障,自己完成了任务后,还得等别的工作线程也完成了之后才能继续干别的事情。

2024-01-30 16:55:41 800

原创 ThreadPoolExecutor源码阅读

ThreadPoolExecutor是一个异步Executor,其背后使用线程池来执行用户提交的任务。ThreadPoolExecutor拥有很多可以配置的参数,用户可以在不同的使用场景中使用不同配置的线程池以便效率最大化。这个抽象类实现了ExecutorService,提供如下几个方法的默认实现:submit, invokeAny, invokeAll这个类定义了一个新方法:newTaskFor,这个方法返回一个RunnableFuture,默认的实现类为FutureTask。

2024-01-29 16:55:15 880

原创 FutureTask源码阅读

FutureTask是Future的一个实现,提供了可取消的异步任务执行。void run();作为Future,为什么实现了Runnable而不是Callable呢,因为实现Runnable接口可以方便地将这个任务交给Executor执行,然后任务内部封装了一个Callable对象,并且在run方法中最终会调用Callable,并将结果保存在内部,当调用get的时候获取结果。

2024-01-22 14:39:36 914

原创 JDK9 - VarHandle小记

在开始之前,有必要点明一下虽只字未提但贯穿全文的核心,从而知道我们使用某些API的目的是什么:VarHandle/Unsafe提供了比volatile关键字更弱的变量访问方式,合理地利用它们可以让我们程序可以在符合运行预期的话情况下提高性能,这里的“弱”指的是约束更少。所谓约束,举个例子,我们在多线程共享变量时,完全不加同步/互斥约束的话可能会导致程序出错,但如果加的约束过头了,比如每个线程访问共享变量时都套一把大锁,又会极大降低并发量。

2024-01-19 15:43:43 375

原创 WeakHashMap源码阅读

了解过WeakReference这个类的都知道,当WeakReference引用的对象不再被强引用时就会被GC回收,此时在若引用上尝试获取对象会返回null。WeakHashMap就利用了弱引用的这个特性,将键保存在弱引用中,当键不再被强引用的时候,尝试获取entry上的键就会返回null,然后WeakHashMap就会自动清除这个entry以节省内存。

2024-01-18 16:12:18 849

原创 LinkedHashMao & LinkedHashSet源码阅读

LinkedHashMap继承于HashMap,在看本篇之前需要先看过HashMap & HashSet源码阅读。相比HashMap,LinkedHashMap增加了一个特性:迭代顺序与插入顺序相同,没别的。LinkedHashMap在HashMap的基础上,根据节点插入/访问的先后顺序将所有节点用双指针串起来,实现了迭代顺序与插入/访问的顺序相同的特性。另外,因为LinkedHashMap可以直接获取到最老的节点,因此进一步支持用户通过继承LinkedHashMap实现键值对缓存。

2024-01-17 18:23:57 323

原创 HashMap & HashSet源码阅读

HashMap是Map接口的一个实现,采用哈希表实现的键值对集合,键和值都允许为null。HashMap 的特殊存储结构使得在获取指定元素前需要经过哈希运算,得到目标元素在哈希表中的位置,然后再进行少量比较即可得到元素,这使得 HashMap 的查找效率贼高。由于是基于哈希的Map,元素之间没有特定的顺序。

2024-01-17 14:40:15 823

原创 PriorityQueue源码阅读

在JCF相关基础类接口/抽象类源码阅读中介绍Queue接口时说过:虽然名义上是队列,但不一定是FIFO,也可以是优先队列,也可以是LIFO。总而言之Queue只是提供“入队”和“出队”的语义,而出入队顺序并不作规定,即在给定入队顺序下,出队顺序由子类定义这篇要介绍的就是优先队列PriorityQueue// 长// 宽// 计算面积});

2024-01-15 16:36:55 808

原创 LinkedList & ArrayDeque源码阅读

从功能上看,LinkedList同时实现了List接口和Deque接口,也就是说它既可以看作一个顺序容器,又可以看作一个队列(Queue),同时又可以看作一个栈(Stack这样看来,LinkedList简直就是个全能冠军。当你需要使用栈或者队列时,可以考虑使用LinkedList,一方面是因为Java官方已经声明不建议使用Stack类,更遗憾的是,Java里根本没有一个叫做Queue的类(它是个接口名字)。关于栈或队列,现在的首选是ArrayDeque,它有着比。

2024-01-12 13:33:05 965

原创 ArrayList源码阅读

ArrayList实现了List接口,是顺序容器,即元素存放的数据与放进去的顺序相同,允许放入null元素,底层通过数组实现。除该类未实现同步外,其余跟Vector大致相同。每个ArrayList都有一个容量(capacity),表示底层数组的实际大小,容器内存储元素的个数不能多于当前容量。当向容器中添加元素时,如果容量不足,容器会自动增大底层数组的大小。

2024-01-08 12:33:38 1022

原创 JCF相关基础类接口/抽象类源码阅读

JCF(Java Collections Framework)为Java开发者提供了通用的容器,而每个可以直接拿来用的容器又实现了很多接口,并且有些接口方法还有default实现,为了更好地掌握JCF的整体结构,甚至以后需要到自己开发容器的时候,对应该实现哪些接口可以做到了然于胸。接口嘛,一方面是为了实现多态,另一方面是为了规范,而且接口的方法一般不会实现,因此更多的是通过看文档注释来了解这个接口是干什么的。下面按照依赖关系顺序分析,先介绍被依赖的接口/类。

2024-01-05 14:55:59 355

原创 ReentrantReadWriteLock源码阅读

ReentrantReadWriteLock是可重入读写锁,所谓可重入锁指的是占有锁的线程继续在这个锁上调用lock直接加锁成功,当然,lock与unlock的调用次数最终数量要相等,否则不会释放锁。而不可重入锁则是lock成功后再lock就会被阻塞。第二个线程此时要获取读锁第二个线程此时要获取写锁第一个线程先占有读锁成功失败第一个线程先占有写锁失败失败在读多写少的场景下,相ReentrantReadWriteLock比普通的ReentrantLock具有更高的并发量。

2023-12-29 14:47:37 761

原创 ReentrantLock源码阅读

ReentrantLock是可重入独占锁,所谓可重入指的是占有锁的线程继续在这个锁上调用lock直接加锁成功,当然,lock与unlock的调用次数最终数量要相等,否则不会释放锁。而不可重入锁则是lock成功后再lock就会被阻塞。ReentrantLock基于AQS(AbstractQueuedSynchronizer),详情请看AbstractQueuedSynchronizer源码阅读。

2023-12-27 21:10:18 735

原创 AbstractQueuedSynchronizer源码阅读

acquire完成的功能其实就是不断自旋获取锁,获取不到就阻塞,醒来后继续自旋,然后阻塞,如此往复。为了实现公平的特性(FIFO),队列中只有第一个有效节点才会去tryAcquire,并且是多次tryAcquire,比如在还没生成节点前会tryAcquire一次,阻塞前tryAcquire至少一次,唤醒后会tryAcquire一次。一些疑问点:为什么第一个有效节点被正常唤醒后(非超时/中断)却还有可能获取不到锁,不是FIFO的吗?

2023-12-27 11:31:30 382

原创 LockSupport源码阅读

本人的源码阅读主要聚焦于类的使用场景,一般只在java层面进行分析,没有深入到一些native方法的实现。并且由于知识储备不完整,很可能出现疏漏甚至是谬误,欢迎指出共同学习相比mutex这个概念来说,LockSupport更像是信号量,不过与信号量最大区别在于LockSupport的"资源计数"最大只有1,叫做,下面直接介绍两个核心方法park和unpark,其他的方法基本都是基于这两个方法重载或扩展而来。

2023-12-23 01:22:58 801

原创 ThreadLocal阅读

假设场景:有两个不同的数据库源,并且这俩数据库在业务代码中都得被多线程共享,那么自然会为这两个数据库分别设置一个ThreadLocal,来使得数据库连接在不同够的线程中隔离。可以发现Thread与ThreadLocal形成一种多对多的关系,如何做到呢,就靠ThreadLocalMap(Thread的成员变量这里先把它看成一个键为ThreadLocal值为Object的普通map。就能获取到该Thread在这个ThreadLocal上对应的资源了(在这里是数据库连接)。

2023-12-18 16:44:47 793

原创 可拓展哈希

然后再放一个key=C(hash©的值被老师的视频挡住了,就不放图片了),哈希值为hash©,并且hash©高两位也是10,查询directory也要放到第二个bucket,但此时bucket满了,就将该bucket分裂,其他bucket不用变动,那么directory应该怎么变动呢?我们传统静态hash的过程是hash函数后直接将值存入对应的bucket,但是在可扩展hash中,首先经过hash函数存入Directory中(左),再由directory指向对应的bucket(右)。

2023-05-06 00:07:59 1060

原创 MIT 6.824实验小记

MIT 6.824实验小记~

2022-12-07 23:40:51 334

原创 Go context包使用

context包定义了Context类型,它在API边界和进程之间,携带timeout、取消信号和其他用于请求环境的值。

2022-08-02 14:07:42 216

原创 Go log包使用

日志包提供了方便的携带多样化信息的输出,比如日期、调用者行号等,为我们找bug或者分析问题提供了强有力的工具。

2022-07-31 12:25:59 399

原创 Go sync包使用

sync包提供了常见的并发编程原语,比如互斥锁Mutex。在一般的业务代码中,除了 Once和 WaitGroup外,sync包中的原语一般用不上,更多的一般用 chan来实现同步和通信。

2022-07-30 18:35:34 478

原创 CLion创建C/C++文件时添加模板代码

参考链接File -> Setting -> Editor -> File and Code Templates选择Files选项卡,选择要要添加模板代码的文件类型在输入框中写入模板代码(关于作者,时间什么的,参考链接有说)要注意的是,#开头的代码,要用#[[…]]包起来...

2020-02-11 17:38:26 13714 8

API函数大全

详细的api大全

2017-04-16

空空如也

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

TA关注的人

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