java架构师课程学习心得-第2篇-TCP握手挥手和事务隔离和synchronized

单点系统重难点记录

前言

上篇文章讲了一些学习的内容和学习方法,这篇文章就整点纯干货,讲讲课程中一些重难点。

一、TCP握手和挥手机制

1.先说说TCP协议的特点

1)它提供面向连接、可靠、有序、字节流传输服务。使用前需要先建立tcp连接
2)tcp协议的数据包中重要标志位,ACK确认信号,SYN建立连接,FIN关闭连接
3)tcp协议速度慢,占用资源多,web服务一般使用tcp协议

2.TCP的三次握手

建立连接,三次握手,过程如下:
下面的seq表示序列号,标记此次连接
第一次握手:客户端发送请求:SYN=1,seq=x -->> 服务端
第二次握手:服务端接收到请求,然后回复:SYN=1,seq=x,seq=y,ack_seq=x+1 -->> 客户端
第三次握手:客户端接收到回复,再发出确认信号,建立连接成功:ACK=1,seq=x+1,ack_seq=y+1 -->> 服务端

三次握手可以想象成打电话的场景,如下:
客:你能听到我吗?
服:我可以听到,你能听到我吗?
客:我可以听到,我们开始通话吧!

问题:为什么一定要三次握手,两次握手不行吗?
:不行,缺少最后一次握手,服务端无法确定客户端是否接收到了他的回复

3.TCP的四次挥手

关闭连接,四次挥手,过程如下:
第一次挥手:客户端发送请求:FIN,seq=u
第二次挥手:服务端接收到请求,然后回复:ACK=1,seq=v,ack_seq=u+1
第三次挥手:服务端再发出确认信号:FIN=1,ACK=1,seq=w,ack_seq=u+1
第四次挥手:客户端接收后,然后回复:ACK=1,seq=u+1,ack_seq=w+1,发出信息后等待一会,没有接收到服务端的信息,则关闭连接:

四次挥手可以想象成打电话的场景,如下:
客:我们结束通话吧
服:好的,可以结束
服:我准备好结束了
客:好的,那你关闭连接吧
客:等待一会,看服务端还会不会发消息,时间过了,没有收到消息,那我关闭连接

下图是整个握手和挥手的过程
在这里插入图片描述

二、数据库事务隔离原理

1.什么是事务隔离?

任何支持事务的数据库,都必须具备四个特性,分别是:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability),也就是我们常说的事务ACID,这样才能保证事务((Transaction)中数据的正确性。
而事务的隔离性就是指,多个并发的事务同时访问一个数据库时,一个事务不应该被另一个事务所干扰,每个并发的事务间要相互进行隔离。

2.数据库中的三种读操作

环境说明,一张student表,里面有三条数据,分别是id=1,name=小红;id=2,name=小明;id=3,name=小亮

1.脏读

某天A事务往表中插入了一条数据 insert into student value(4,“小黑”),但没有提交事务
之后B事务又来查询表的所有数据,里面出现了小黑这条数据,这种情况就叫脏读既读到了没有提交的数据

2.不可重复读

某天,事务A访问了数据库,他要查看ID是1的学生的名字,于是执行了

select Name from student where ID = 1;

这时,事务B来了,因为ID是1的学生改名字了,所以要更新一下,然后提交了事务。

update student set Name = ‘大红’ where ID = 1;

接着,事务A还想再看看ID是1的牛人的名字,于是又执行了

select Name from student where ID = 1;

结果,两次读出来的ID是1的牛人名字竟然不相同,这就是不可重复读既一个事务修改了另一个事务正在读取的那一行记录

3.幻读

某天,事务A访问了数据库,他想要看看数据库的有多少学生,于是执行了

select count(*) from student;

这时候,事务B来了,往数据库加入了一个新的学生,并提交了事务。

insert into student values(4, ‘小紫’);

这时候,事务A忘了刚才的学生都有哪些了,于是又执行了。

select count(*) from student;

结果,第一次有三个学生,第二次有四个学生。

相信这个时候事务A就蒙了,刚才发生了什么?这种情况就叫***幻读***,既一个事务在另一个事务做数据统计的时候修改了增删了记录或者修改了要统计的字段

2.数据库事务隔离级别

为了防止出现脏读、不可重复读、幻读等情况,我们就需要根据我们的实际需求来设置数据库的隔离级别。

1.读未提交(Read Uncommitted)

读未提交,顾名思义,就是可以读到未提交的内容。

因此,在这种隔离级别下,查询是不会加锁的,也由于查询的不加锁,所以这种隔离级别的一致性是最差的,可能会产生“脏读”、“不可重复读”、“幻读”。

如无特殊情况,基本是不会使用这种隔离级别的。

2.读提交(Read Committed)

读提交,顾名思义,就是只能读到已经提交了的内容。

这是各种系统中最常用的一种隔离级别,也是SQL Server和Oracle的默认隔离级别。这种隔离级别能够有效的避免脏读,但除非在查询中显示的加。

那为什么“读提交”同“读未提交”一样,都没有查询加锁,但是却能够避免脏读呢?这就要说道另一个机制“快照(snapshot)”,而这种既能保证一致性又不加锁的读也被称为“快照读(Snapshot Read)”

假设没有“快照读”,那么当一个更新的事务没有提交时,另一个对更新数据进行查询的事务会因为无法查询而被阻塞,这种情况下,并发能力就相当的差。而“快照读”就可以完成高并发的查询,不过,“读提交”只能避免“脏读”,并不能避免“不可重复读”和“幻读”。

3.可重复读(Repeated Read)

可重复读,顾名思义,就是专门针对“不可重复读”这种情况而制定的隔离级别,自然,它就可以有效的避免“不可重复读”。而它也是MySql的默认隔离级别。

在这个级别下,普通的查询同样是使用的“快照读”,但是,和“读提交”不同的是,当事务启动时,就不允许进行“修改操作(Update)”了,而“不可重复读”恰恰是因为两次读取之间进行了数据的修改,因此,“可重复读”能够有效的避免“不可重复读”,但却避免不了“幻读”,因为幻读是由于“插入或者删除操作(Insert or Delete)”而产生的。

4.串行化(Serializable)

这是数据库最高的隔离级别,这种级别下,事务“串行化顺序执行”,也就是一个一个排队执行。

这种级别下,“脏读”、“不可重复读”、“幻读”都可以被避免,但是执行效率奇差,性能开销也最大,所以基本没人会用。

同步关键字synchronized和锁升级

1.synchronized的特点

1)用于实例方法、静态方法时,隐式指定锁对象
2)用于代码块时,显示指定锁对象
3)锁的作用域:对象锁,类锁,方法锁,分布式锁
4)引申:如果是多个线程,怎么办
5)特性:可重入,独享,悲观锁
6)锁优化:锁消除:(开启锁消除参数:-XX:+DoEscapeAnalysis -XX:+ELiminateLocks),jvm认为只有一个线程访问对象时,就会消除锁
7)锁粗化:JDK做了锁粗化的优化,但是我们自己可以从代码层面优化,(将多个同步代码块合并为一)

2.锁的状态

1)锁的状态记录在对象头中,对象头中有三个字段Mark word、Class meta address、array lenth,锁的信息就在mark Word中
2)对象头中记录着如下信息:
a.锁状态和锁标志位:无锁态(01),轻量级锁(00),重量级锁(10),GC标记(11),偏向锁(01)
b.线程id,epoch,分代年龄,是否偏向锁
c.指向线程栈中,轻量级锁的指针,指向重量级锁的指针,对象监视器地址
在这里插入图片描述

3.锁的升级过程

1)当线程t1访问对象时,t1获得偏向锁,对象头中会记录t1的id和epoch
2)当线程t2也来访问对象时,jvm会在全局安全点上暂停持有偏向锁的t1,然后检查t1是否存活
3)t1不存活,则t2线程获得偏向锁
4)t1存活,对象头中的记录变为未锁定状态
5)再次判断t1,t2是否仍然处于竞争锁的情况
6)如果存在竞争,则将锁升级为轻量锁
7)如果后面又来了更多的线程争抢对象,则锁会升级为重量级锁,并交由对象监视器管理
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值