如何解决多线程造成的数据库死锁

如何解决多线程造成的数据库死锁,第1张

线程是很容易造成死锁,一般情况下死锁都是因为并发 *** 作引起的。我不懂JAVA,但死锁这个问题每种开发工具和数据库都会碰到解决办法是:

1、程序方面优化算法(如有序资源分配法、银行算法等),在一个程序里,能不用多线程更新同一张数据库表 尽量不要用,如果要用,其避免死锁的算法就很复杂。

2、数据库方面设置等待超时时间

3、发生死锁后直接KILL掉数据库进程

如图所示啊,石杉大佬画的redisson分布式锁原理。

大概总结下,保证我们的key落到一个集群里,并且加锁 *** 作是基于lua脚本的原子性 *** 作,对于锁延迟由watch dog控制。

具体可以看 >

大致罗列一下:

一、全局解释器锁(GIL)

1、什么是全局解释器锁

每个CPU在同一时间只能执行一个线程,那么其他的线程就必须等待该线程的全局解释器,使用权消失后才能使用全局解释器,即使多个线程直接不会相互影响在同一个进程下也只有一个线程使用cpu,这样的机制称为全局解释器锁(GIL)。GIL的设计简化了CPython的实现,使的对象模型包括关键的内建类型,如:字典等,都是隐含的,可以并发访问的,锁住全局解释器使得比较容易的实现对多线程的支持,但也损失了多处理器主机的并行计算能力。

2、全局解释器锁的好处

1)、避免了大量的加锁解锁的好处

2)、使数据更加安全,解决多线程间的数据完整性和状态同步

3、全局解释器的缺点

多核处理器退化成单核处理器,只能并发不能并行。

4、GIL的作用:

多线程情况下必须存在资源的竞争,GIL是为了保证在解释器级别的线程唯一使用共享资源(cpu)。

二、同步锁

1、什么是同步锁?

同一时刻的一个进程下的一个线程只能使用一个cpu,要确保这个线程下的程序在一段时间内被cpu执,那么就要用到同步锁。

2、为什么用同步锁?

因为有可能当一个线程在使用cpu时,该线程下的程序可能会遇到io *** 作,那么cpu就会切到别的线程上去,这样就有可能会影响到该程序结果的完整性。

3、怎么使用同步锁?

只需要在对公共数据的 *** 作前后加上上锁和释放锁的 *** 作即可。

4、同步锁的所用:

为了保证解释器级别下的自己编写的程序唯一使用共享资源产生了同步锁。

三、死锁

1、什么是死锁?

指两个或两个以上的线程或进程在执行程序的过程中,因争夺资源或者程序推进顺序不当而相互等待的一个现象。

2、死锁产生的必要条件?

互斥条件、请求和保持条件、不剥夺条件、环路等待条件

3、处理死锁的基本方法?

预防死锁、避免死锁(银行家算法)、检测死锁(资源分配)、解除死锁:剥夺资源、撤销进程

四、递归锁

在Python中为了支持同一个线程中多次请求同一资源,Python提供了可重入锁。这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。递归锁分为可递归锁与非递归锁。

五、乐观锁

假设不会发生并发冲突,只在提交 *** 作时检查是否违反数据完整性。

六、悲观锁

假定会发生并发冲突,屏蔽一切可能违反数据完整性的 *** 作。

python常用的加锁方式:互斥锁、可重入锁、迭代死锁、互相调用死锁、自旋锁。

BFS(广度优先搜索)是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。

BFS算法的核心思想就是把一些问题抽象成图

BFS相对DFS最主要的区别是: BFS找到的路径一定是最短的,但代价是空间复杂度比DFS大很多

BFS常出现的场景: 问题的本质就是让你在 一幅图 中找到从起点 start 到终点 target 的最近距离,BFS算法其实就是在干这事

一般来说在找最短路径的时候用BFS,其他时候还是用DFS多一些

传统的BFS框架是从起点开始向四周扩散,遇到终点时停止;而双向BFS则是从起点和终点同时开始扩散,当两边有交集的时候停止

使用双向BFS的前提是,必须提前知道终点在哪里

无论传统BFS还是双向BFS,无论做不做优化,从Big O 的衡量标准看,空间复杂度都是一样的

有一个带四个圆形拨轮的转盘锁,每个拨轮都有0-9共10个数字,

每个拨轮可以上下旋转: 例如把9变成0, 0变成9,每次旋转只能将一个拨轮旋转 一下

引言

之前自己在用redis来实现分布式锁的时候都是基于单个Redis实例,也就是说Redis本身是有单点故障的,Redis的官方文档介绍了一种"自认为"合理的算法,Redlock来实现分布式Redis下的分布式锁。

Martin Kleppmann写了一篇文章分析Redlock。然后redis的作者写了一篇反驳的文章这里。加油。

Redlock实现库

单点Redis锁

先简单回顾一下单点的Redis锁是怎么实现的。

获取锁

客户端A在Redis上设置一个特定的键值对,同时给一个超时时间(避免死锁)。其他客户端在访问的时候先看看这个key是否已经存在,并且值等于my_random_value。如果已存在就等待,否则就获取成功,执行业务代码。resource_name和my_random_value是所有客户端都知道并且共享的。

释放锁

对比key获取到的对应的value是否相等,如果相等,就删除(释放),否则就返回失败。

之前也写过一篇文章。

单点Redis锁的缺陷

这个缺陷其实很明显,如果只有一个Redis实例,这个挂了,所有依赖他的服务都挂了。显然不太适合大型的应用。

简单的Redis主从架构碰到的问题

为了避免单点故障,我们给Redis做一个Master/Slave的主从架构,一个Master,一台Slave。下面就会碰到这么一个问题。下面是使用场景。

Redlock算法

假设我们有N(假设5)个Redis master实例,所有节点相互独立,并且业务系统也是单纯的调用,并没有什么其他的类似消息重发之类的辅助系统。下面来模拟一下算法:

锁的释放

所谓死锁:是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。由于资源占用是互斥的,当某个进程提出申请资源后,使得有关进程在无外力协助下,永远分配不到必需的资源而无法继续运行,这就产生了一种特殊现象死锁。

虽然进程在运行过程中,可能发生死锁,但死锁的发生也必须具备一定的条件,死锁的发生必须具备以下四个必要条件。

锁一般是指用版本号机制或CAS算法实现的锁。

一般是在数据表中加上一个数据版本号version字段,表示数据被修改的次数,当数据被修改时,version值会加一。当线程A要更新数据值时,在读取数据的同时也会读取version值,在提交更新时,若刚才读取到的version值为当前数据库中的version值相等时才更新,否则重试更新 *** 作,直到更新成功。

以上就是关于如何解决多线程造成的数据库死锁全部的内容,包括:如何解决多线程造成的数据库死锁、Redisson实现分布式锁原理、Python中的各种锁等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/sjk/9517665.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-29
下一篇2023-04-29

发表评论

登录后才能评论

评论列表(0条)

    保存