Entry

ThreadLocal到底有没有内存泄漏?从源码角度来剖析一波

丶灬走出姿态 提交于 2020-10-07 05:26:54
1. 前言 ThreadLocal 也是一个使用频率较高的类,在框架中也经常见到,比如 Spring。 有关 ThreadLocal 源码分析的文章不少,其中有个问题常被提及:ThreadLocal 是否存在内存泄漏? 不少文章对此讲述比较模糊,经常让人看完脑子还是一头雾水,我也有此困惑。因此找时间跟小伙伴讨论了一番,总算对这个问题有了一定的理解,这里记录和分享一下,希望对有同样困惑的朋友们有所帮助。当然,若有理解不当的地方也欢迎指正。 啰嗦就到这里,下面先从 ThreadLocal 的一个应用场景开始分析吧。 2. 应用场景 ThreadLocal 的应用场景不少,这里举个简单的栗子:单点登录拦截。 也就是在处理一个 HTTP 请求之前,判断用户是否登录: 若未登录,跳转到登录页面; 若已登录,获取并保存用户的登录信息。 先定义一个 UserInfoHolder 类保存用户的登录信息,其内部用 ThreadLocal 存储,示例如下: public class UserInfoHolder { private static final ThreadLocal<Map<String, String>> USER_INFO_THREAD_LOCAL = new ThreadLocal<>(); public static void set (Map<String, String>

Ubuntu下搭建Eclipse开发环境

自作多情 提交于 2020-10-07 04:53:49
1. 官方下载 2. 解压到指定目录 可先解压到当前目录然后 mv eclipse /opt (1)如果想把eclipse目录的更改为root拥有,可以执行下面的命令 sudo chown -R root:root /opt/eclipse 在/usr/bin目录下创建一个启动脚本eclipse (2)用下面的命令来创建: sudo gedit /usr/bin/eclipse 然后在该文件中添加以下内容: #!/bin/sh export MOZILLA_FIVE_HOME=”/usr/lib/mozilla/” export ECLIPSE_HOME=”/opt/eclipse” $ECLIPSE_HOME/eclipse $* (3)让修改该脚本的权限,让它变成可执行,执行下面的命令: sudo chmod +x /usr/bin/eclipse 3. 在Applications(应用程序)菜单上添加一个图标 用文本编辑器在/usr/share/applications目录里新建一个名为eclipse.desktop的启动器,如下面的命令: sudo vi /usr/share/applications/eclipse.desktop 或者 sudo gedit /usr/share/applications/eclipse.desktop 然后在文件中添加下列内容:

Raft 协议原理详解

喜夏-厌秋 提交于 2020-10-06 08:58:00
前言 先简单聊聊分布式算法的重要性问题 在分布式微服务系统的项目中,最重要的是 如何选择或者设计合适的算法,来解决一致性问题以及可用性等相关问题 而分布式系统的最关键之处,在于根据场景的需要选择合适的算法,在一致性和可用性之间权衡(注:因为分区容错性是必须满足的),而权衡妥协的关键在于是否了解各个算法的特点,对于其他技术也适用。找到影响选择的因素,了解各个技术的特点,根据场景需要权衡选择。 下面是一些分布式算法的比较: 当然本章不是介绍所有的分布式算法,我也没法仅仅使用一篇文章就把上面表格中覆盖的分布式算法知识清晰的讲述。 所有我们重点讲解的是现在分布式算法或者说现在分布式数据一致性首选算法:Raft 算法 raft是工程上使用较为广泛的强一致性、去中心化、高可用的分布式协议。在这里强调了是在工程上,因为在学术理论界,最耀眼的还是大名鼎鼎的Paxos。但Paxos是:少数真正理解的人觉得简单,尚未理解的人觉得很难,大多数人都是一知半解。本人也花了很多时间、看了很多材料也没有真正理解。直到看到raft的论文,两位研究者也提到,他们也花了很长的时间来理解Paxos,他们也觉得很难理解,于是研究出了raft算法。    raft是一个共识算法(consensus algorithm),所谓共识,就是多个节点对某个事情达成一致的看法,即使是在部分节点故障、网络延时、网络分割的情况下

用var声明变量,在java中居然有这么多细节,你都了解么?

假装没事ソ 提交于 2020-10-05 16:56:39
简介 Java SE 10引入了局部变量的类型推断。早先,所有的局部变量声明都要在左侧声明明确类型。 使用类型推断,一些显式类型可以替换为具有初始化值的局部变量保留类型var,这种作为局部变量类型 的var类型,是从初始化值的类型中推断出来的。 关于此功能存在一定的争议。有些人对它的简洁性表示欢迎,其他人则担心它剥夺了阅读者看重的类型信息 ,从而损害了代码的可读性。这两边观点都是对的。它可以通过消除冗余信息使代码更具有可读性,也可以 通过删除有用的信息来降低代码的可读性。另外一个观点是担心它会被滥用,从而导致编写更糟糕的Java代码。 这也是事实,但它也可能会导致编写更好的代码。像所有功能一样,使用它必须要判断。何时该使用, 何时不该使用,没有一系列规则。 局部变量声明不是孤立存在的;周边的代码可以影响甚至压倒使用var的影响。本文档的目的是检查周边代码 对var声明的影响,解释一些权衡,并提供有效使用var的指南。 使用原则 P1. 阅读代码比编写代码更重要 代码的读取频率远高于编写代码。此外,在编写代码时,我们通常要有整体思路,并且要花费时间; 在阅读代码的时候,我们经常是上下文浏览,而且可能更加匆忙。是否以及如何使用特定语言功能应该取决 于它对未来读者的影响,而不是它的作者。较短的程序可能比较长的程序更可取,但是过多地简写程序会 省略对于理解程序有用的信息

ARM SMMU的原理与IOMMU

本秂侑毒 提交于 2020-10-05 13:58:25
首先放一个社区iommupatch的网址:https://lore.kernel.org/linux-iommu/ 1: arm smmu的原理 1.1: smmu 基本知识 如上图所示,smmu 的作用和mmu 类似,mmu作用是替cpu翻译页表将进程的虚拟地址转换成cpu可以识别的物理地址。同理,smmu的作用就是替设备将dma请求的地址,翻译成设备真正能用的物理地址,但是当smmu bypass的时候,设备也可以直接使用物理地址来进行dma; 1.2: smmu 的数据结构 smmu的重要的用来dma地址翻译的数据结构都是放在内存中的,由smmu的寄存器保存着这些表在内存中的基地址,首先就是StreamTable(STE),这ste 表既包含stage1的翻译表结构也包含stage2的翻译结构,所谓stage1负责VA 到 PA的转换,stage2负责IPA到PA的转换。 接下来我们重点看一下这个STE的结构,到底在内存中是如何组织的; 对smmu来说,一个smmu可以给很多个设备服务,所以,在smmu里面为了区分的对每个设备进行管理,smmu 给每一个设备一个ste entry,那设备如何定位这个ste entry呢?对于一个smmu来说,我们给他所管理的每个设备一个唯一的device id,这个device id又叫 stream id;对于设备比较少的情况下

ConcurrentHashMap 怎么聊出花来?

…衆ロ難τιáo~ 提交于 2020-10-05 09:06:54
前言 之前,我们已经在HashMap上面暴打了面试官,没看过的读者可以看看哦 HashMap 怎么聊出花来? 。今天!,辉先森带读者一起解读ConcurrentHashMap! 一、为什么有CurrentHashMap? 通过前章的学习哦,我们有了解到,HashMap做的优化以及其遗留的线程安全的问题。 那为什么要多线程呢? 1. 更好的利用处理器 在 多核 场景下,使用多线程技术,将计算逻辑分配搭配多个处理器核心,就会显著减少程序的处理时间,并且随核数的加入而变得更加的有效率。 2. 更快的相应时间 在多线程下,可将数据一致性不强的操作派给其他线程处理。 好处:相应用户请求线程能更快的处理完成,缩短响应时间,提高用户体验。 二、解决HashMap线程不安全 1.HashTable hashtable对 get/put所有相关的操作都加上 synchronized 标志。虽然实现了线程安全,但是 代价太大 了。相当于对整个哈希表加了一把大锁,这样在竞争激烈的并发场景 性能太差 了。(不推荐考虑) 2.ConcurrentHashMap 使用 Segment分段锁 技术,将数据分成一段一段的存储,然后给每一段数据配一把锁,当一个线程占用锁访问其中一段数据时,不阻塞访问其他段的数据,可以看成是有多个hashtable。 好处:使用Segment分段锁技术减少了锁的粒度提高了并发的能力。

HashMap 为什么会导致 CPU 100%?文章看不懂?来看这个视频吧!——面试突击 006 期

不想你离开。 提交于 2020-10-05 06:47:24
哈喽,大家好,我是老王,欢迎来到 Java 面试突击,我们今天来开始第 6 期的内容。 本期的问题是:HashMap 为什会导致 CPU 运行 100%?这是一个比较常见的经典问题了,但是有很多人读者朋友给我反馈,尼玛,看文章根本看不懂啊?Sun 公司都不知道这个问题的原因吧?不,是 Oracle 公司都不知道这个问题的原因吧?面试官怕也不知道这个的答案吧? 咳咳,作为一个很正经的面试官,我觉得这个问题一点都不重要,重要的是你不知道答案啊。好的,下一位面试者请进,您先回去等通知吧。 为了避免这种尴尬的事情发生,今天我们来好好聊一下这个问题,毕竟技能再手,才能吊打面试官不是? 正文 这个问题相关的知识点,有以下几个: H``` ashMap 的底层数据结构是什么? 什么是哈希碰撞?如何该解决这个问题? 什么是扩展因子?它有什么用? 还有对 HashMap 源码的理解,为什么 HashMap 会导致死循环? 视频版答案 视频内容如下: 图文答案 1.HashMap 的底层数据结构 先来说 HashMap 的底层数据结构,看过 HashMap 的源码我们就会发现,JDK 1.7 和 JDK 1.8 HashMap 的组成是不同的,JDK 1.7 HashMap 的组成是数组 + 链表的形式,而 JDK 1.8 新增了红黑树的数据结构,当 HashMap 中的链表长度大于 8 时

聊聊claudb的NotificationManager

断了今生、忘了曾经 提交于 2020-10-04 23:28:33
序 本文主要研究一下claudb的NotificationManager NotificationManager claudb-1.7.1/src/main/java/com/github/tonivade/claudb/event/NotificationManager.java public class NotificationManager implements PatternSubscriptionSupport { private final DBServerContext server; private final ExecutorService executor = Executors.newSingleThreadExecutor(); public NotificationManager(DBServerContext server) { this.server = server; } public void start() { // nothing to do } public void stop() { executor.shutdown(); } public void enqueue(Event event) { executor.execute(() -> patternPublish(server, event.getChannel(), event

Linux文件系统

北城以北 提交于 2020-10-04 09:12:27
引入:VFS VFS(Virtual Filesystem Switch)称为虚拟文件系统或虚拟文件系统转换,是一个 内核软件层 ,在具体的文件系统之上抽象的一层,用来处理与Posix文件系统相关的所有调用, 给各种文件系统提供一个通用的接口,使上层的应用程序能够使用通用的接口访问不同文件系统,同时也为不同文件系统的通信提供了媒介 。 VFS提供了一个抽象层,将POSIX API接口与不同存储设备的具体接口实现进行了分离,使得底层的文件系统类型、设备类型对上层应用程序透明。 linux下“一切皆文件”是Unix/Linux的基本哲学之一。unix标准文件: 普通文件,目录文件,符号链接文件,设备文件,管道文件 。 通用文件模型 数据类型 Superblock inode dentry file 功能 存储文件系统元数据 文件相关的元数据 文件(目录)名称和具体的inode的对应关系,缓存最近最常访问的文件或目录,提示系统性能 存储内容 文件系统类型、大小、状态(存放于磁盘文件系统控制块) 文件的所有者(用户、组)、访问时间、文件类型等(存放于磁盘文件控制块) 是否存储在介质中 是 是 否 否 何时创建 mount时从介质中读取,并常驻内存 重要成员 s_list、 涉及操作函数 *s_op 维护 所有SB对象以双向循环链表链接在一起 是否缓存 是 Superblock

深度解密 Go 语言之 sync.map

我只是一个虾纸丫 提交于 2020-10-04 04:31:33
工作中,经常会碰到并发读写 map 而造成 panic 的情况,为什么在并发读写的时候,会 panic 呢?因为在并发读写的情况下,map 里的数据会被写乱,之后就是 Garbage in, garbage out ,还不如直接 panic 了。 目录 是什么 有什么用 如何使用 源码分析 数据结构 Store Load Delete LoadOrStore Range 其他 总结 参考资料 是什么 Go 语言原生 map 并不是线程安全的,对它进行并发读写操作的时候,需要加锁。而 sync.map 则是一种并发安全的 map,在 Go 1.9 引入。 sync.map 是线程安全的,读取,插入,删除也都保持着常数级的时间复杂度。 sync.map 的零值是有效的,并且零值是一个空的 map。在第一次使用之后,不允许被拷贝。 有什么用 一般情况下解决并发读写 map 的思路是加一把大锁,或者把一个 map 分成若干个小 map,对 key 进行哈希,只操作相应的小 map。前者锁的粒度比较大,影响效率;后者实现起来比较复杂,容易出错。 而使用 sync.map 之后,对 map 的读写,不需要加锁。并且它通过空间换时间的方式,使用 read 和 dirty 两个 map 来进行读写分离,降低锁时间来提高效率。 如何使用 使用非常简单,和普通 map 相比,仅遍历的方式略有区别: