volatile
可见性
底层是内存屏障,jdk1.5后才生效。
对volatile变量写,会在volatile变量的修改操作之后加上写屏障,写屏障之前所有变量的修改操作都回刷新到主内存中。
读,会在volatile变量的读取操作之前加上读屏障,读屏障之后所有变量的读取操作都会从主内存中去读。
有序性
保证写屏障之前的变量不会指令重排
保证读屏障之后的变量不会指令重排
为什么volatile不能保证原子性
对于i=1这个赋值操作,由于其本身是原子操作,因此在多线程程序中不会出现不一致问题,但是对于i++这种复合操作,即使使用volatile关键字修饰也不能保证操作的原子性,可能会引发数据不一致问题。
12private volatile int i = 0;i++;
如果启了500条线程并发地去执行i++这个操作 最后的结果i是小于500的
1234567i++操作可以被拆分为三步: 1,线程读取i的值 2、i进行自增计算 3、刷新回i的值
网上一些博客的解释是:
假设某一时刻i=5,此时有两个线程同时从主存中读取了i的值,那么此时两个线程保存的i的值都是5, 此 ...
开发遇到的问题汇总
java:程序包xxxx不存在问题怎么解决
三种情况:
没导入坐标
依赖的模块包编译出错
要么jar下载的时候出问题
第一种自己看代码
第二种,依赖的模块包重新install,自己install一下
第三种解决方法:创建一个.bat文档然后输入以下代码:
123456REPOSITORY_PATH=[自己maven本地仓库地址]rem 正在搜索...for /f "delims=" %%i in ('dir /b /s "%REPOSITORY_PATH%\*lastUpdated*"') do (del /s /q %%i)rem 搜索完毕pause
双击打开回车就好了。之后打开idea刷新一下。这个脚本是清除所有下载失败的jar包,之后等jar包下载好就行了。
can not get cluster name in registry config ‘service.vgroupMapping.xx‘, please make sure registry
我的项目是使用了nacos作为seata的配置中心,和注册中心,主 ...
redis面试题
开篇
将redis的面试题分两个部分
使用场景
缓存
❤️如果发生了缓存穿透、击穿、雪崩,该如何解决这三种情况都可以通过添加降级限流策略来缓解
缓存穿透缓存击穿缓存雪崩
缓存穿透是客户端请求了一个不存在的数据,在redis缓存中,就会去查询数据库重建缓存,但是因为数据不存在,所以没办法写入缓存,就会导致每次查询都访问数据,所以就有了被人开启大量线程访问,数据库被大量访问崩溃的风险
解决方案一:存空对象,如果数据库查询不存在那就将空对象存入redis,那么下一次查询就不会进入数据库查询,缺点是内存消耗较大
解决方案二:布隆过滤器,布隆过滤器采用位图,存储和查询都是将key经过三次hash,将每次的结果设置为1和比较是否为1,如果都为1则认为redis有数据,放行查询redis,否则拒绝访问,所以布隆过滤器需要在redis缓存预热时,预热布隆过滤器,同时布隆过滤器有一定的误判的概率,一般这个位图的越大,概率越小,所以我们可以设置误判的概率,一般是5%就比较合适,既满足系统可接受的程度,又不会有太大的内存消耗
缓存击穿是指高并发环境下,热点key过期失效了,此时大量线程尝试重建缓存去 ...
InnoDB锁机制
MySQL中的锁,按照锁的粒度分,分为以下三类:
全局锁:锁定数据库中的所有表。
表级锁:每次操作锁住整张表。
行级锁:每次操作锁住对应的行数据。
全局锁
介绍
全局锁就是对整个数据库实例加锁,加锁后整个实例就处于只读状态,后续的DML的写语句,DDL语句,已经更新操作的事务提交语句都将被阻塞。 其典型的使用场景是做全库的逻辑备份,对所有的表进行锁定,从而获取一致性视图,保证数据的完整性。
假设在数据库中存在这样三张表: tb_stock 库存表,tb_order 订单表,tb_orderlog 订单日志表。
在进行数据备份时,先备份了tb_stock库存表。
然后接下来,在业务系统中,执行了下单操作,扣减库存,生成订单(更新tb_stock表,插入tb_order表)。
然后再执行备份 tb_order表的逻辑。
业务中执行插入订单日志操作。
最后,又备份了tb_orderlog表。
此时备份出来的数据,是存在问题的。因为备份出来的数据,tb_stock表与tb_order表的数据不一 致(有最新操作的订单信息,但是库存数没减)。可以使用全局锁解决
语法
加全局锁
...
系统学习算法1-链表双指针技巧
单链表常考的技巧就是双指针,本文就总结一下单链表的基本技巧,这些技巧就是会者不难,难者不会,每个技巧都对应着至少一道算法题:
1、合并两个有序链表
2、链表的分解
3、合并 k 个有序链表
4、寻找单链表的倒数第 k 个节点
5、寻找单链表的中点
6、判断单链表是否包含环并找出环起点
7、判断两个单链表是否相交并找出交点
合并两个有序链表
这是最基本的链表技巧,力扣第 21 题「 合并两个有序链表」就是这个问题:
解法
1234567891011121314151617181920212223242526272829ListNode mergeTwoLists(ListNode l1, ListNode l2) { // 虚拟头结点 ListNode dummy = new ListNode(-1), p = dummy; ListNode p1 = l1, p2 = l2; while (p1 != null && p2 != null) { // 比较 p1 和 p2 两个指针 // ...
华为机考入门题
入门题
HJ5 进制转换(输入处理)
描述
写出一个程序,接受一个十六进制的数,输出该数值的十进制表示。
数据范围:保证结果在 1≤n≤2^31−1
输入描述:
输入一个十六进制的数值字符串。
输出描述:
输出该数值的十进制字符串。不同组的测试用例用\n隔开。
题解
1234567891011121314151617181920212223242526import java.util.Scanner;// 注意类名必须为 Main, 不要有任何 package xxx 信息public class Main { public static void main(String[] args) { Scanner in = new Scanner(System.in); // 注意 hasNext 和 hasNextLine 的区别 while (in.hasNextLine()) { // 注意 while 处理多个 case String s = in.nextLine(); ...
MySQL面试题
B树和B+树的不同
B树每个节点数据项都包含了完整的行数据,他没有冗余索引,所以有可能查询的时候直接在根节点查询出来,所以它的查找不够稳定
B+树完整行数据都存储在叶子节点,其他冗余节点存储的是索引值和子节点(数据页)的最小值的地址,因为冗余节点只存储索引地址,所以数据页大小相同,在同高度的树下,B+树会比B树存储更多的数据,同时在叶子节点之间都有指向前后节点的指针方便处理范围查询。
注:Mysql中B+树一个节点默认是16k
为什么InnoDB表必须建主键,并推荐使用整型自增主键?
因为InnoDB表不建主键的话,MySQL会尝试自己查找一列没有数据重复的列作为键,如果没有则MySQL自己创建一列隐形id作为主键构建聚集索引,而这些操作都是可以避免的。
选择整型是为了便于比较,比如字符型就需要逐个字符比较,自增是为了避免整理数据页的问题,因为一个节点就是一张数据页,如果现在需要插入一个主键id小于当前页最后一条数据id大于倒数第二条数据id的数据,B+树又必须要是排序好的数据结构,所以就需要将最后一条数据修改移动,而自增就可以只需要在这种情况,新增数据页就好了
为什么非主键索引结构叶 ...
InnoDB事务
事务基础
事务
事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。
特性
原子性(Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败。
一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态。
隔离性(lsolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。
持久性(Durability):事务t旦提交或回滚,它对数据库中的数据的改变就是永久的。
redo log
作用
重做日志,记录的是事务提交时数据页的物理修改,是用来实现事务的持久性。
该日志文件由两部分组成:重做日志缓冲(redo log buffer)以及重做日志文件(redo log file) ,前者是在内存中,后者在磁盘中。
当对缓冲区的数据进行增删改之后,会首先将操作的数据页的变化,记录在redo log buffer中。在事务提交时,会将redo log buffer中的数据刷新到redo log磁盘文件中,在刷新脏页到磁盘 ...
InnoDB架构
逻辑存储结构
表空间
表空间是InnoDB存储引擎逻辑结构的最高层, 如果用户启用了参数 innodb_file_per_table(在
8.0版本中默认开启) ,则每张表都会有一个表空间(.ibd文件),一个mysql实例可以对应多个表空 间,用于存储记录、索引等数据。
段
段,分为数据段(Leaf node segment)、索引段(Non-leaf node segment)、回滚段 (Rollback segment),InnoDB是索引组织表,数据段就是B+树的叶子节点, 索引段即为B+树的 非叶子节点。段用来管理多个Extent(区)。
区
区,表空间的单元结构,每个区的大小为1M。 默认情况下, InnoDB存储引擎页大小为16K, 即一 个区中一共有64个连续的页。
页
页,是InnoDB 存储引擎磁盘管理的最小单元,每个页的大小默认为 16KB。为了保证页的连续性,
InnoDB 存储引擎每次从磁盘申请 4-5 个区。
行
行,InnoDB 存储引擎数据是按行进行存放的。
在行中,默认有两个隐藏字段:
Trx_id:每次对某条记录进行改动时,都会把对应的事务id赋 ...