既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Go语言开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
- 若P1保持了资源R1,P2保持了资源R2,系统处于不安全状态,因为这两个进程再向前推进,便可能发生死锁
- 例如,当P1运行到P1:Request(R2)时,将因R2已被P2占用而阻塞;当P2运行到P2:Request(R1)时,也将因R1已被P1占用而阻塞,于是发生进程死锁
3.死锁产生的4个必要条件?
产生死锁的必要条件:
- 互斥条件:进程要求对所分配的资源进行排它性控制,即在一段时间内某资源仅为一进程所占用。
- 请求和保持条件:当进程因请求资源而阻塞时,对已获得的资源保持不放。
- 不剥夺条件:进程已获得的资源在未使用完之前,不能剥夺,只能在使用完时由自己释放。
- 环路等待条件:在发生死锁时,必然存在一个进程–资源的环形链。
4.解决死锁的基本方法
预防死锁:
- 资源一次性分配:一次性分配所有资源,这样就不会再有请求了:(破坏请求条件)
- 只要有一个资源得不到分配,也不给这个进程分配其他的资源:(破坏请保持条件)
- 可剥夺资源:即当某进程获得了部分资源,但得不到其它资源,则释放已占有的资源(破坏不可剥夺条件)
- 资源有序分配法:系统给每类资源赋予一个编号,每一个进程按编号递增的顺序请求资源,释放则相反(破坏环路等待条件)
1、以确定的顺序获得锁
如果必须获取多个锁,那么在设计的时候需要充分考虑不同线程之前获得锁的顺序。按照上面的例子,两个线程获得锁的时序图如下:
如果此时把获得锁的时序改成:
那么死锁就永远不会发生。 针对两个特定的锁,开发者可以尝试按照锁对象的hashCode值大小的顺序,分别获得两个锁,这样锁总是会以特定的顺序获得锁,那么死锁也不会发生。问题变得更加复杂一些,如果此时有多个线程,都在竞争不同的锁,简单按照锁对象的hashCode进行排序(单纯按照hashCode顺序排序会出现“环路等待”),可能就无法满足要求了,这个时候开发者可以使用银行家算法,所有的锁都按照特定的顺序获取,同样可以防止死锁的发生,该算法在这里就不再赘述了,有兴趣的可以自行了解一下。
2、超时放弃
当使用synchronized关键词提供的内置锁时,只要线程没有获得锁,那么就会永远等待下去,然而Lock接口提供了boolean tryLock(long time, TimeUnit unit) throws InterruptedException方法,该方法可以按照固定时长等待锁,因此线程可以在获取锁超时以后,主动释放之前已经获得的所有的锁。通过这种方式,也可以很有效地避免死锁。 还是按照之前的例子,时序图如下:
避免死锁:
- 预防死锁的几种策略,会严重地损害系统性能。因此在避免死锁时,要施加较弱的限制,从而获得 较满意的系统性能。由于在避免死锁的策略中,允许进程动态地申请资源。因而,系统在进行资源分配之前预先计算资源分配的安全性。若此次分配不会导致系统进入不安全的状态,则将资源分配给进程;否则,进程等待。其中最具有代表性的避免死锁算法是银行家算法。
- 银行家算法:首先需要定义状态和安全状态的概念。系统的状态是当前给进程分配的资源情况。因此,状态包含两个向量Resource(系统中每种资源的总量)和Available(未分配给进程的每种资源的总量)及两个矩阵Claim(表示进程对资源的需求)和Allocation(表示当前分配给进程的资源)。安全状态是指至少有一个资源分配序列不会导致死锁。当进程请求一组资源时,假设同意该请求,从而改变了系统的状态,然后确定其结果是否还处于安全状态。如果是,同意这个请求;如果不是,阻塞该进程知道同意该请求后系统状态仍然是安全的。
5.检测死锁
- 首先为每个进程和每个资源指定一个唯一的号码;
- 然后建立资源分配表和进程等待表。
6.解除死锁
当发现有进程死锁后,便应立即把它从死锁状态中解脱出来,常采用的方法有:
- 剥夺资源:从其它进程剥夺足够数量的资源给死锁进程,以解除死锁状态;
- 撤消进程:可以直接撤消死锁进程或撤消代价最小的进程,直至有足够的资源可用,死锁状态.消除为止;所谓代价是指优先级、运行代价、进程的重要性和价值等。
7.死锁检测
1、Jstack命令
jstack是java虚拟机自带的一种堆栈跟踪工具。jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息。 Jstack工具可以用于生成java虚拟机当前时刻的线程快照。线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。 线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做什么事情,或者等待什么资源。
2、JConsole工具
Jconsole是JDK自带的监控工具,在JDK/bin目录下可以找到。它用于连接正在运行的本地或者远程的JVM,对运行在Java应用程序的资源消耗和性能进行监控,并画出大量的图表,提供强大的可视化界面。而且本身占用的服务器内存很小,甚至可以说几乎不消耗。
参考博文:https://blog.csdn.net/jonnyhsu_0913/article/details/79633656
四、延时和抖动
延时和抖动是相互关联的两个东西,但是它们并不相同。延时是网络中的一个重要指标,它由四个关键部分组成:处理延时(processing delay),排队延时(queueing delay),传输延时(transmission delay)和传播延时(propagation delay)。它会影响用户体验,并可能因多种因素而发生变化。抖动是基于延时产生的—具体而言,就是前后延时的值不一致。抖动是两个数据包延时值之间的差异。它通常会导致丢包和网络拥塞。虽然延时和抖动有很多共同点和关联,但是它们并不相同。
1.什么是延时(delay)?
延时是网络中的一项重要指标,可衡量数据从一个端点移动到另一个端点所需的时间。网络延时通常在几秒钟的时间范围内,并且可以更具许多因素进行更改,包括端点的位置,数据包的大小以及流量大小。
延时(delay)与延迟(latency)有何不同
延迟和延时相互联系紧密,并且很多时候可以混用。但是,他们并不总是相同的。延时是数据从一个端点传输到另一个端点所花费的时间。然而,延迟可以表示两个量。
延迟有时被认为是数据包从一个端点传输到另一个端点所用的时间,这与单向延时是一样的。
但更多的情况,延迟表示的是往返时间。往返时间包括发送数据包所需的时间加上它返回所需的时间。这不包括在目的地处理数据包所需的时间。
网络监控工具可以确定给定网络上的精确往返时间。可以从发送处计算往返时间,因为它跟踪数据包发送的时间,并在确认返回时计算差值。但是,两个端点之间的延时可能难以确定,因为发送端没有到达接收端的时间信息。
2.延时的组成
延时可以理解为四个关键延时部分的组合:处理延时,排队延时,传输延时和传播延时。
- 处理延时:处理延时是系统分析数据包报头并确定数据包必须发送到何处的时间。这很大程度上取决于路由表中的条目,系统中数据结构的执行以及硬件实现。
- 排队延时:排队延时是数据包排队和发送之间的时间。这取决于数据流量的大小,流量类型以及实现哪些路由器队列算法。不同的算法可以调整系统偏好的延时,或者对所有流量要求相同的延时。
- 传输延时:传输延时是将数据包的数据推入线路所需的时间。这会根据数据包的不同大小和带宽大小而不同。这并不取决于传输线的距离,因为它仅仅是将包中数据推入传输线的时间,而不是沿着传输线到达接收端的时间。
- 传播延时:传播延时是与从发送端传输到接收端的数据包的第一个比特相关的时间。这通常被称为距离延时,并且因此数据比特受到传播距离和传播速度的影响。
这些延时组合在一起构成网络中的总延时。往返时间由这些延时和接收端到发送端之间的时间组成。
3.延时的影响
延时主要会影响用户体验。在严格的音频通话中,150毫秒的延时是非常明显的并且会影响用户。在严格的视频通话中,认为400毫秒是可辨识的。将这两种呼叫功能集中在一起后,联合的音频和视频呼叫应该保持同步,并且延时要少于150毫秒以不影响用户。但是,一般来说,延时尽可能低是非常重要的。无论如何,ITU建议将网络延时保持在100毫秒以下。
4.什么是抖动?
在网络上连续传输的数据包即便使用相同的路径,也会有不同的延时。这是由于分组交换网络固有的两个关键原因造成的。第一,数据包被单独路由。第二,网络设备接收队列中的数据包,因此无法保证延时调度不变。
每个数据包之间的这种延时不一致称为抖动。对于实时通信而言,这可能是一个相当大的问题,包括IP电话,视频会议和虚拟桌面基础架构。抖动可能由网络上的许多因素引起,并且每个网络都有延时时间变化。
5.抖动会导致什么后果?
- 丢包:当数据包不是均匀的到达接收端时,接收端必须进行弥补并尝试更正。在某些情况下,接收端无法进行适当的更正,并丢失数据包。就最终用户体验而言,这可以有多种呈现出的形式。比如,如果用户正在观看视频并且画面变成像素化,这就是潜在抖动的指示。
- 网络拥塞:网络设备无法发送相同数据的流量,因此他们的数据包缓冲区已满并开始丢弃数据包。如果端点上的网络没有干扰,则每个数据包都会到达。但是,如果端点缓冲区满了,会使数据包到达的越来越晚,导致抖动。这被称为初期拥塞(incipient congestion)。通过监视抖动,可以观察到初期拥塞。同样,如果出现初期网络拥塞,则说明抖动正在迅速变化。
当网络设备开始丢弃数据包,并且端点没有收到数据包时就会发生拥塞。终端可能会要求重发丢失的数据包,这会导致拥塞崩溃。
需要注意的是接收端不会直接导致拥塞,也不会丢弃数据包。请想象一条高速公路,其中有旅店A和旅店B。旅店B拥挤不是由于B没有足够的停车位而造成的。拥挤是由A引起的,所以它会不断地将公路上的骑车送到B旅店。
6.我该如何补偿抖动?
为了弥补抖动,在连接的接收端使用抖动缓冲区。抖动缓冲区收集并存储传入数据包,以便它可以确定如何以一致的间隔发送它们。
- 静态抖动缓冲—其在系统的硬件中实现,并且通常由制造商配置。
- 动态抖动缓冲—其在系统软件中实现,并由管理员进行配置。他们可对缓冲进行调整以适应网络变化。
7.播放延时
播放延时是数据包到达时和播放时间之间的延时。当抖动缓冲区存储传入数据包并等待以均匀间隔分配它们时,这会增加数据包到达时间与播放时间之间的时间,也被称为播放延时。这个延时是由抖动缓冲区引入的,因为它负责规定传入数据包何时分发。
8.总结
延时和抖动天生就紧密相连,但它们其实并不同。延时是数据从网络上的一个端点移动到另一个端点所花费的时间。这是一个受多种因素影响的复杂的值。另一方面,抖动是两个数据包之间的延时差异。同样,它也可能是由网络上的几个因素造成的。尽管抖动和延时有相似之处,但是抖动仅仅是基于延时产生的而已,但不等于它。
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!