JUC-1-基础回顾
基础知识
并发(concurrent)
同一个实体上的的多个事件
一台处理器上同时处理多个任务
并行(parallel)
在不同实体上的多个事件
多台处理器上同时处理多任务
进程
在系统中运行的一个应用程序就是一个进程,每一个进程都有它自己的内存空间和系统资源
线程
轻量级进程,在同一个进程内会有一个或多个线程,是大多数操作系统进行时序调度的基本单元
管程
Monitor(平时所说的锁),一种同步机制,保证(同一时间)只有一个线程可以访问被保护的数据和代码。JVM中同步是基于进入和退出监视器对象(Monitor,管程对象)来实现道德,每个对象实例都会有一个Monitor对象。Monitor对象会和Java对象一同创建并销毁,底层由C++实现
用户线程
一般情况下不做特别说明配置,默认都是用户线程。用户线程是系统的工作线程,它会完成这个程序需要完成的业务操作
守护线程
守护是一种特殊的线程为其它线程服务,在后台默默地完成一些系统性的服务(比如垃圾回收线程)
守护线程作为一个服务线程,没有服务对象就没有必要继续运行。如果用户线程全部结束,意味着程序需要 ...
MySQL高级篇-5-存储引擎
查看存储引擎
查看存储引擎
1show engines;
设置系统默认的存储引擎
查看默认的存储引擎
123show variables like '%storage_engine%';-- 或SELECT @@default_storage_engine;
修改默认的存储引擎
如果在创建表的语句中没有显式指定表的存储引擎的话,那就会默认使用InnoDB作为表的存储引擎。 如果我们想改变表的默认存储引擎的话,可以这样写启动服务器的命令行
1SET DEFAULT_STORAGE_ENGINE=MyISAM;
或者修改my.cnf文件:
1default-storage-engine=MyISAM
12# 重启服务systemctl restart mysqld.service
设置表的存储引擎存储引擎是负责对表中的数据进行提取和写入工作的,可以为 不同的表设置不同的存储引擎 ,不同的表可以有不同的物理存储结构、不同的提取和写入方式。
创建表时指定存储引擎创建表的语句都没有指定表的存储引擎,那就会使用默认的存储引擎 InnoDB 。如果我们 ...
MySQL高级篇-4-逻辑架构
逻辑架构剖析服务器处理客户端请求以查询请求为例剖析服务器进程对客户端进程发送的请求做出怎样的处理得到最后结果
第1层:连接层 系统(客户端)访问 MySQL 服务器前,做的第一件事就是建立 TCP 连接。经过三次握手建立连接成功后, MySQL 服务器对 TCP 传输过来的账号密码做身份认证、权限获取。
用户名或密码不对,会收到一个Access denied for user错误,客户端程序结束执行
用户名密码认证通过,会从权限表查出账号拥有的权限与连接关联,之后的权限判断逻辑,都将依 赖于此时读到的权限
TCP 连接收到请求后,必须要分配给一个线程专门与这个客户端的交互。所以还会有个线程池,去走后 面的流程。每一个连接从线程池中获取线程,省去了创建和销毁线程的开销。
第2层:服务层
SQL Interface:SQL接口
接收用户的SQL命令,并且返回用户需要查询的结果。比如SELECT … FROM就是调用SQL
MySQL支持DML(数据操作语言)、DDL(数据定义语言)、存储过程、视图、触发器、自定 义函数等多种SQL语言接口
Pars ...
Redis-6-原理篇-网络模型
用户空间和内核态空间进程的寻址空间划分成两部分:内核空间、用户空间
应用程序也好,还是内核空间也好,都是没有办法直接去物理内存的,而是通过分配一些虚拟内存映射到物理内存中,内核和应用程序去访问虚拟内存时,就需要一个虚拟地址,地址是一个无符号的整数
比如一个32位的操作系统,他的带宽就是32,他的虚拟地址就是2的32次方,也就是说他寻址的范围就是0~2的32次方, 这片寻址空间对应的就是2的32个字节,就是4GB,这个4GB,会有3个GB分给用户空间,会有1GB给内核系统
在linux中,他们权限分成两个等级,0和3,用户空间只能执行受限的命令(Ring3),而且不能直接调用系统资源,必须通过内核提供的接口来访问内核空间可以执行特权命令(Ring0),调用一切系统资源,所以一般情况下,用户的操作是运行在用户空间,而内核运行的数据是在内核空间的,而有的情况下,一个应用程序需要去调用一些特权资源,去调用一些内核空间的操作,所以此时他俩需要在用户态和内核态之间进行切换。
比如,Linux系统为了提高IO效率,会在用户空间和内核空间都加入缓冲区:
写数据时,要把用户缓冲数据拷贝到内核缓冲区,然 ...
Redis-6-原理篇-Redis数据结构
SDS
Why SDS
字符串是Redis中最常用的一种数据结构。不过Redis没有直接使用C语言中的字符串,因为C语言字符串存在很多问题:
获取字符串长度的需要通过运算
非二进制安全
不可修改
SDS
Redis构建了一种新的字符串结构,称为简单动态字符串(Simple Dynamic String),简称SDS。
Redis是C语言实现的,其中SDS是一个结构体,源码如下:
SDS底层结构
例如,一个包含字符串“name”的sds结构如下:
SDS之所以叫做动态字符串,是因为它具备动态扩容的能力,例如一个内容为“hi”的SDS:
假如我们要给SDS追加一段字符串“,Amy”,这里首先会申请新内存空间:
如果新字符串小于1M,则新空间为扩展后字符串长度的两倍+1;
如果新字符串大于1M,则新空间为扩展后字符串长度+1M+1。称为内存预分配。
SDS优点
获取字符串长度时间复杂度 $O(1)$
支持动态 扩容
减少内存分配次数
二进制安全
intsetIntSet是Redis中set集合的一种实现方式,基于整数数组来实现,并且具备长度可变、有序等特 ...
JVM 内存与垃圾回收篇-3-运行时数据区
运行时数据区
内存是非常重要的系统资源,是硬盘和CPU 的中间仓库及桥梁承载着操作系统和应用程序的实时运行。JVM内存布局规定了Java在运行过程中内存申请、分配、管理的策略,保证了JM的高效稳定运行。不同的JVM对于内存的划分方式和管理机制存在着部分差异。结合JVM虚拟机规范,来探讨一下经典的JVM内存布局。
Java虚拟机定义了若干种程序运行期间会使用到的运行时数据区,其中有一些会随着虚拟机启动而创建,随着虚拟机退出而销毁。另外一些则是与线程一一对应的,这些与线程对应的数据区域会随着线程开始和结束而创建和销毁。
灰色的为单独线程私有的,红色的为多个线程共享的。即:
每个线:独立包括程序计数器、栈、本地栈。
线程间共享:堆、堆外内存(永久代或元空间、代码缓存)
程序计数器
PC寄存器用来存储指向下一条指令的地址,也即将要执行的指令代码。由执行引擎读取下一条指令。
它是一块很小的内存空间,几乎可以忽略不记。也是运行速度最快的存储区域。
在JVM规范中,每个线程都有它自己的程序计数器,是线程私有的,生命周期与线程的生命周期保持一致。
任何时间一个线程都只有一个方法在执行(当 ...