精华内容
下载资源
问答
  • 本文将要为您介绍的是MSSQL死锁产生原因及解决方法,教程操作方法:  一、 什么是死锁  死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去....
  • 来源:r6d.cn/qDxdMysql锁类型一、锁类型介绍: MySQL有三种锁的级别:页级、表级、行级。表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度...

    来源:r6d.cn/qDxd

    Mysql 锁类型

    一、锁类型介绍:

    MySQL有三种锁的级别:页级、表级、行级。

    • 表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。

    • 行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。

    • 页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般

    算法:

    • next KeyLocks锁,同时锁住记录(数据),并且锁住记录前面的Gap

    • Gap锁,不锁记录,仅仅记录前面的Gap

    • Recordlock锁(锁数据,不锁Gap)

    • 所以其实 Next-KeyLocks=Gap锁+ Recordlock锁

    二、死锁产生原因和示例

    1、产生原因:

    所谓死锁:是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程。表级锁不会产生死锁.所以解决死锁主要还是针对于最常用的InnoDB。

    死锁的关键在于:两个(或以上)的Session加锁的顺序不一致。

    那么对应的解决死锁问题的关键就是:让不同的session加锁有次序

    2、产生示例:

    案例一

    需求:将投资的钱拆成几份随机分配给借款人。

    起初业务程序思路是这样的:

    投资人投资后,将金额随机分为几份,然后随机从借款人表里面选几个,然后通过一条条select for update 去更新借款人表里面的余额等。

    例如两个用户同时投资,A用户金额随机分为2份,分给借款人1,2

    B用户金额随机分为2份,分给借款人2,1

    由于加锁的顺序不一样,死锁当然很快就出现了。

    对于这个问题的改进很简单,直接把所有分配到的借款人直接一次锁住就行了。

    Select * from xxx where id in (xx,xx,xx) for update
    

    在in里面的列表值mysql是会自动从小到大排序,加锁也是一条条从小到大加的锁

    例如(以下会话id为主键):

    Session1:

    mysql> select * from t3 where id in (8,9) for update;
    +----+--------+------+---------------------+
    | id | course | name | ctime               |
    +----+--------+------+---------------------+
    |  8 | WA     | f    | 2016-03-02 11:36:30 |
    |  9 | JX     | f    | 2016-03-01 11:36:30 |
    +----+--------+------+---------------------+
    rows in set (0.04 sec)
    

    Session2:

    select * from t3 where id in (10,8,5) for update;
    

    锁等待中……

    其实这个时候id=10这条记录没有被锁住的,但id=5的记录已经被锁住了,锁的等待在id=8的这里 不信请看

    Session3:

    mysql> select * from t3 where id=5 for update;
    

    锁等待中

    Session4:

    mysql> select * from t3 where id=10 for update;
    +----+--------+------+---------------------+
    | id | course | name | ctime               |
    +----+--------+------+---------------------+
    | 10 | JB     | g    | 2016-03-10 11:45:05 |
    +----+--------+------+---------------------+
    row in set (0.00 sec)
    

    在其它session中id=5是加不了锁的,但是id=10是可以加上锁的。

    案例二

    在开发中,经常会做这类的判断需求:根据字段值查询(有索引),如果不存在,则插入;否则更新。

    以id为主键为例,目前还没有id=22的行

    Session1:

    select * from t3 where id=22 for update;
    Empty set (0.00 sec)
    

    session2:

    select * from t3 where id=23  for update;
    Empty set (0.00 sec)
    

    Session1:

    insert into t3 values(22,'ac','a',now());
    

    锁等待中……

    Session2:

    insert into t3 values(23,'bc','b',now());
    

    ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

    当对存在的行进行锁的时候(主键),mysql就只有行锁。

    当对未存在的行进行锁的时候(即使条件为主键),mysql是会锁住一段范围(有gap锁)

    锁住的范围为:

    (无穷小或小于表中锁住id的最大值,无穷大或大于表中锁住id的最小值)

    如:如果表中目前有已有的id为(11 , 12)

    那么就锁住(12,无穷大)

    如果表中目前已有的id为(11 , 30)

    那么就锁住(11,30)

    对于这种死锁的解决办法是:

    insert into t3(xx,xx) on duplicate key update `xx`='XX';
    

    用mysql特有的语法来解决此问题。因为insert语句对于主键来说,插入的行不管有没有存在,都会只有行锁

    案例三

    mysql> select * from t3 where id=9 for update;
    +----+--------+------+---------------------+
    | id | course | name | ctime               |
    +----+--------+------+---------------------+
    |  9 | JX     | f    | 2016-03-01 11:36:30 |
    +----+--------+------+---------------------+
     
    row in set (0.00 sec)
    

    Session2:

    mysql> select * from t3 where id<20 for update;
    

    锁等待中

    Session1:

    mysql> insert into t3 values(7,'ae','a',now());
    

    ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

    这个跟案例一其它是差不多的情况,只是session1不按常理出牌了,

    Session2在等待Session1的id=9的锁,session2又持了1到8的锁(注意9到19的范围并没有被session2锁住),最后,session1在插入新行时又得等待session2,故死锁发生了。

    这种一般是在业务需求中基本不会出现,因为你锁住了id=9,却又想插入id=7的行,这就有点跳了,当然肯定也有解决的方法,那就是重理业务需求,避免这样的写法。

    案例四

    一般的情况,两个session分别通过一个sql持有一把锁,然后互相访问对方加锁的数据产生死锁。

    案例五

    两个单条的sql语句涉及到的加锁数据相同,但是加锁顺序不同,导致了死锁。

    案例六

    死锁场景如下:

    表结构:

    CREATE TABLE dltask (
        id bigint unsigned NOT NULL AUTO_INCREMENT COMMENT ‘auto id’,
        a varchar(30) NOT NULL COMMENT ‘uniq.a’,
        b varchar(30) NOT NULL COMMENT ‘uniq.b’,
        c varchar(30) NOT NULL COMMENT ‘uniq.c’,
        x varchar(30) NOT NULL COMMENT ‘data’,   
        PRIMARY KEY (id),
        UNIQUE KEY uniq_a_b_c (a, b, c)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT=’deadlock test’;
    

    a,b,c三列,组合成一个唯一索引,主键索引为id列。

    事务隔离级别:

    RR (Repeatable Read)

    每个事务只有一条SQL:

    delete from dltask where a=? and b=? and c=?;
    

    SQL的执行计划:

    死锁日志:

    众所周知,InnoDB上删除一条记录,并不是真正意义上的物理删除,而是将记录标识为删除状态。(注:这些标识为删除状态的记录,后续会由后台的Purge操作进行回收,物理删除。但是,删除状态的记录会在索引中存放一段时间。) 在RR隔离级别下,唯一索引上满足查询条件,但是却是删除记录,如何加锁?InnoDB在此处的处理策略与前两种策略均不相同,或者说是前两种策略的组合:对于满足条件的删除记录,InnoDB会在记录上加next key lock X(对记录本身加X锁,同时锁住记录前的GAP,防止新的满足条件的记录插入。) Unique查询,三种情况,对应三种加锁策略,总结如下:

    此处,我们看到了next key锁,是否很眼熟?对了,前面死锁中事务1,事务2处于等待状态的锁,均为next key锁。明白了这三个加锁策略,其实构造一定的并发场景,死锁的原因已经呼之欲出。但是,还有一个前提策略需要介绍,那就是InnoDB内部采用的死锁预防策略。

    • 找到满足条件的记录,并且记录有效,则对记录加X锁,No Gap锁(lock_mode X locks rec but not gap);

    • 找到满足条件的记录,但是记录无效(标识为删除的记录),则对记录加next key锁(同时锁住记录本身,以及记录之前的Gap:lock_mode X);

    • 未找到满足条件的记录,则对第一个不满足条件的记录加Gap锁,保证没有满足条件的记录插入(locks gap before rec);

    死锁预防策略

    InnoDB引擎内部(或者说是所有的数据库内部),有多种锁类型:事务锁(行锁、表锁),Mutex(保护内部的共享变量操作)、RWLock(又称之为Latch,保护内部的页面读取与修改)。

    InnoDB每个页面为16K,读取一个页面时,需要对页面加S锁,更新一个页面时,需要对页面加上X锁。任何情况下,操作一个页面,都会对页面加锁,页面锁加上之后,页面内存储的索引记录才不会被并发修改。

    因此,为了修改一条记录,InnoDB内部如何处理:

    • 根据给定的查询条件,找到对应的记录所在页面;

    • 对页面加上X锁(RWLock),然后在页面内寻找满足条件的记录;

    • 在持有页面锁的情况下,对满足条件的记录加事务锁(行锁:根据记录是否满足查询条件,记录是否已经被删除,分别对应于上面提到的3种加锁策略之一);

    相对于事务锁,页面锁是一个短期持有的锁,而事务锁(行锁、表锁)是长期持有的锁。因此,为了防止页面锁与事务锁之间产生死锁。InnoDB做了死锁预防的策略:持有事务锁(行锁、表锁),可以等待获取页面锁;但反之,持有页面锁,不能等待持有事务锁。

    根据死锁预防策略,在持有页面锁,加行锁的时候,如果行锁需要等待。则释放页面锁,然后等待行锁。此时,行锁获取没有任何锁保护,因此加上行锁之后,记录可能已经被并发修改。因此,此时要重新加回页面锁,重新判断记录的状态,重新在页面锁的保护下,对记录加锁。如果此时记录未被并发修改,那么第二次加锁能够很快完成,因为已经持有了相同模式的锁。但是,如果记录已经被并发修改,那么,就有可能导致本文前面提到的死锁问题。

    以上的InnoDB死锁预防处理逻辑,对应的函数,是row0sel.c::row_search_for_mysql()。感兴趣的朋友,可以跟踪调试下这个函数的处理流程,很复杂,但是集中了InnoDB的精髓。

    剖析死锁的成因

    做了这么多铺垫,有了Delete操作的3种加锁逻辑、InnoDB的死锁预防策略等准备知识之后,再回过头来分析本文最初提到的死锁问题,就会手到拈来,事半而功倍。

    首先,假设dltask中只有一条记录:(1, ‘a’, ‘b’, ‘c’, ‘data’)。三个并发事务,同时执行以下的这条SQL:

    delete from dltask where a=’a’ and b=’b’ and c=’c’;
    

    并且产生了以下的并发执行逻辑,就会产生死锁:

    上面分析的这个并发流程,完整展现了死锁日志中的死锁产生的原因。其实,根据事务1步骤6,与事务0步骤3/4之间的顺序不同,死锁日志中还有可能产生另外一种情况,那就是事务1等待的锁模式为记录上的X锁 + No Gap锁(lock_mode X locks rec but not gap waiting)。这第二种情况,也是”润洁”同学给出的死锁用例中,使用MySQL 5.6.15版本测试出来的死锁产生的原因。

    此类死锁,产生的几个前提:

    • Delete操作,针对的是唯一索引上的等值查询的删除;(范围下的删除,也会产生死锁,但是死锁的场景,跟本文分析的场景,有所不同)

    • 至少有3个(或以上)的并发删除操作;

    • 并发删除操作,有可能删除到同一条记录,并且保证删除的记录一定存在;

    • 事务的隔离级别设置为Repeatable Read,同时未设置innodb_locks_unsafe_for_binlog参数(此参数默认为FALSE);(Read Committed隔离级别,由于不会加Gap锁,不会有next key,因此也不会产生死锁)

    • 使用的是InnoDB存储引擎;(废话!MyISAM引擎根本就没有行锁)

    如何检测代码运行是否出现死锁

    • https://blog.csdn.net/kk185800961/article/details/79528841

    • https://blog.csdn.net/yucaifu1989/article/details/79400446


    【推荐阅读】
    

    蚂蚁金服开源增强版 Spring Boot 的研发框架!

    10个常见的软件架构模式

    面试官:来说说单点登录的三种实现方式

    延时队列实现的几种姿势

    卧槽!我随便写的一个 API 竟获得 2.5 亿的访问量...

    IntelliJ IDEA 15款 神级超级牛逼插件推荐

    直观讲解一下 RPC 调用和 HTTP 调用的区别!

    展开全文
  • 当多个用户并发地存取数据 时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。加锁是实现数据库并 发控制的一个非常重要的技术。在...
  • 数据库--死锁产生原因及解决方法

    千次阅读 2020-03-15 23:20:17
    当多个用户并发地存取数据时,就会产生多个事务同时存取统一数据的情况。如果对并发操作没有相应的控制就可能会导致读取和存储不正确的数据,破坏了数据库的一致性。 加锁(读锁和写锁)是一种控制方法,但当两个...

     数据库与操作系统一样,是一个多用户使用的共享资源。当多个用户并发地存取数据时,就会产生多个事务同时存取统一数据的情况。如果对并发操作没有相应的控制就可能会导致读取和存储不正确的数据,破坏了数据库的一致性。

       加锁(读锁和写锁)是一种控制方法,但当两个事务要一组有冲突的锁,而不能将事务继续下去的话,就会出现死锁。

    死锁1:

    用户A访问表A(锁住了表A),然后又访问表B;用户B访问表B,然后企图访问表A;这时候用户A和B就会相互等待对方释放原本持有的锁,而进入僵持,也就死锁了。

    解决方法:对于多表的操作,尽力按照相同的顺序进行处理,避免同时锁定两个资源。必须同时锁定两个资源时,要保证在任何时刻都应该按照想同的顺序来锁定资源。比如让用户A先锁定表A再表B,那用户B也是先锁定表A再B。

    死锁2:

    用户A查询一条记录,然后修改这条记录;这时用户B修改这条记录。 用户A的事务里锁从查询的共享锁企图上升到独占锁,而用户B里的独占锁由于A有共享锁存在所以必须等A释放掉共享锁,但A由于B的独占锁无法上锁到独占锁也就不可能释放共享锁,于是就出现了死锁。

    解决方法:1.避免同时对同一条记录操作。

    2.使用乐观锁(基于数据版本记录机制)控制。

    3.使用悲观锁控制(开销比较大)。

    死锁3:

    如果在事务中执行了一条不满足条件的update语句,则执行全表扫描,把行级锁上升为表级锁,多个这样的事务执行后,很容易产生死锁和阻塞。当表中的数据量非常大而所以建的过少或不合适时候,也会经常发生全表扫描,出现类似情况。

    解法方法:SQL语句中不要使用太复杂的关联多表的查询,使用“explain”对SQL语句进行分析,对于全表扫描的SQL语句,建立相应的索引进行优化。

     

     

     

    展开全文
  • 主要介绍了java中产生死锁原因及如何避免,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
  • C++--问题9--死锁,死锁产生原因,处理方法 1.什么是死锁 多线程和多进程改善了系统资源的利用率并提高了系统 的处理能力,但他们的并发操作,互相等待的过程,从而带来了死锁问题。 2.可抢占资源 可抢占资源...

    C++--问题9--死锁,死锁产生原因,处理方法


    1.什么是死锁

          多线程和多进程改善了系统资源的利用率并提高了系统 的处理能力,但他们的并发操作,互相等待的过程,从而带来了死锁问题。

    2.可抢占资源

          可抢占资源指某进程在获得这类资源后,该资源可以再被其他进程或系统抢占。对于这类资源是不会引起死锁的。

          CPU 和主存均属于可抢占性资源。

    3.不可抢占资源

            一旦系统把某资源分配给该进程后,就不能将它强行收回,只能在进程用完后自行释放。

            磁带机、打印机等属于不可抢占性资源。

    4.死锁产生的原因

    4.1 竞争不可抢占资源引起死锁

              通常系统中拥有的不可抢占资源,其数量不足以满足多个进程运行的需要,使得进程在运行过程中,会因争夺资源而陷入僵局,如磁带机、打印机等。只有对不可抢占资源的竞争 才可能产生死锁,对可抢占资源的竞争是不会引起死锁的。

    4.2竞争可消耗资源引起死锁

            如:进程通信时引起死锁
            系统中拥有三个进程P1、P2和P3,m1、m2、m3是3可消耗资源。进程P1一方面产生消息m1,将其发送给P2,另一方面要从P3接收消息m3。而进程P2一方面产生消息m2,将其发送给P3,另一方面要从P1接收消息m1。类似的,进程P3一方面产生消息m3,将其发送给P1,另一方面要从P2接收消息m2。
    如果三个进程都先发送自己产生的消息后接收别人发来的消息,则可以顺利的运行下去不会产生死锁,但要是三个进程都先接收别人的消息而不产生消息则会永远等待下去,产生死锁。

    4.3进程推进顺序不当引起死锁

              进程在运行过程中,请求和释放资源的顺序不当,也同样会导致死锁。例如,并发进程 P1、P2分别保持了资源R1、R2,而进程P1申请资源R2,进程P2申请资源R1时,两者都会因为所需资源被占用而阻塞。
    信号量使用不当也会造成死锁。进程间彼此相互等待对方发来的消息,结果也会使得这 些进程间无法继续向前推进。例如,进程A等待进程B发的消息,进程B又在等待进程A 发的消息,可以看出进程A和B不是因为竞争同一资源,而是在等待对方的资源导致死锁。

    5.产生死锁的四个必要条件

    5.1 互斥条件:

            进程要求对所分配的资源(如打印机)进行排他性控制,即在一段时间内某资源仅为一个进程所占有。此时若有其他进程请求该资源,则请求进程只能等待。

    5.2 不可剥夺条件:

             进程所获得的资源在未使用完毕之前,不能被其他进程强行夺走,即只能由获得该资源的进程自己来释放(只能是主动释放)。

    5.3 请求与保持条件(占有且等待):

             进程已经保持了至少一个资源,但又提出了新的资源请求,而该资源已被其他进程占有,此时请求进程被阻塞,但对自己已获得的资源保持不放。

    5.4 循环等待条件:

            存在一种进程资源的循环等待链,链中每一个进程已获得的资源同时被 链中下一个进程所请求。即存在一个处于等待状态的进程集合{Pl, P2, …, pn},其中Pi等 待的资源被P(i+1)占有(i=0, 1, …, n-1),Pn等待的资源被P0占有,如图所示。

             直观上看,循环等待条件似乎和死锁的定义一样,其实不然。按死锁定义构成等待环所 要求的条件更严,它要求Pi等待的资源必须由P(i+1)来满足,而循环等待条件则无此限制。 例如,系统中有两台输出设备,P0占有一台,PK占有另一台,且K不属于集合{0, 1, …, n}。

             Pn等待一台输出设备,它可以从P0获得,也可能从PK获得。因此,虽然Pn、P0和其他 一些进程形成了循环等待圈,但PK不在圈内,若PK释放了输出设备,则可打破循环等待, 如图2-16所示。因此循环等待只是死锁的必要条件。

    以上这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之一不满足,就不会发生死锁。

    6.处理死锁的方法

    预防死锁:通过设置某些限制条件,去破坏产生死锁的四个必要条件中的一个或几个条件,来防止死锁的发生。

    避免死锁:在资源的动态分配过程中,用某种方法去防止系统进入不安全状态,从而避免死锁的发生。常用避免死锁的方法:有序资源分配法,银行家算法(可查看我的另一博客)

    检测死锁:允许系统在运行过程中发生死锁,但可设置检测机构及时检测死锁的发生,并采取适当措施加以清除。

    解除死锁:当检测出死锁后,便采取适当措施将进程从死锁状态中解脱出来。死锁解除的主要方法有:资源剥夺法,撤销进程法,进程回退法。

    展开全文
  • 死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生死锁,这些永远在互相等的进程称为死锁进程
  • 什么是死锁? 所谓死锁,是指多个进程在运行过程中因争夺资源而造成的一种僵局,当进程处于这种僵持状态时,若无外力...产生死锁原因? 可归结为如下两点: a. 竞争资源 系统中的资源可以分为两类: 可剥夺...

    什么是死锁?

    所谓死锁,是指多个进程在运行过程中因争夺资源而造成的一种僵局,当进程处于这种僵持状态时,若无外力作用,它们都将无法再向前推进。 因此我们举个例子来描述,如果此时有一个线程A,按照先锁a再获得锁b的的顺序获得锁,而在此同时又有另外一个线程B,按照先锁b再锁a的顺序获得锁。如下图所示:

    产生死锁的原因?

    可归结为如下两点:

    a. 竞争资源

    • 系统中的资源可以分为两类:
    1. 可剥夺资源,是指某进程在获得这类资源后,该资源可以再被其他进程或系统剥夺,CPU和主存均属于可剥夺性资源;
    2. 另一类资源是不可剥夺资源,当系统把这类资源分配给某进程后,再不能强行收回,只能在进程用完后自行释放,如磁带机、打印机等。
    • 产生死锁中的竞争资源之一指的是竞争不可剥夺资源(例如:系统中只有一台打印机,可供进程P1使用,假定P1已占用了打印机,若P2继续要求打印机打印将阻塞)
    • 产生死锁中的竞争资源另外一种资源指的是竞争临时资源(临时资源包括硬件中断、信号、消息、缓冲区内的消息等),通常消息通信顺序进行不当,则会产生死锁

    b. 进程间推进顺序非法

    • 若P1保持了资源R1,P2保持了资源R2,系统处于不安全状态,因为这两个进程再向前推进,便可能发生死锁
    • 例如,当P1运行到P1:Request(R2)时,将因R2已被P2占用而阻塞;当P2运行到P2:Request(R1)时,也将因R1已被P1占用而阻塞,于是发生进程死锁

    死锁产生的4个必要条件?

    产生死锁的必要条件:

    1. 互斥条件:进程要求对所分配的资源进行排它性控制,即在一段时间内某资源仅为一进程所占用。
    2. 请求和保持条件:当进程因请求资源而阻塞时,对已获得的资源保持不放。
    3. 不剥夺条件:进程已获得的资源在未使用完之前,不能剥夺,只能在使用完时由自己释放。
    4. 环路等待条件:在发生死锁时,必然存在一个进程--资源的环形链。

    解决死锁的基本方法

    预防死锁:

    • 资源一次性分配:一次性分配所有资源,这样就不会再有请求了:(破坏请求条件)
    • 只要有一个资源得不到分配,也不给这个进程分配其他的资源:(破坏请保持条件)
    • 可剥夺资源:即当某进程获得了部分资源,但得不到其它资源,则释放已占有的资源(破坏不可剥夺条件)
    • 资源有序分配法:系统给每类资源赋予一个编号,每一个进程按编号递增的顺序请求资源,释放则相反(破坏环路等待条件)

    1、以确定的顺序获得锁

    如果必须获取多个锁,那么在设计的时候需要充分考虑不同线程之前获得锁的顺序。按照上面的例子,两个线程获得锁的时序图如下:

     如果此时把获得锁的时序改成:

     那么死锁就永远不会发生。 针对两个特定的锁,开发者可以尝试按照锁对象的hashCode值大小的顺序,分别获得两个锁,这样锁总是会以特定的顺序获得锁,那么死锁也不会发生。问题变得更加复杂一些,如果此时有多个线程,都在竞争不同的锁,简单按照锁对象的hashCode进行排序(单纯按照hashCode顺序排序会出现“环路等待”),可能就无法满足要求了,这个时候开发者可以使用银行家算法,所有的锁都按照特定的顺序获取,同样可以防止死锁的发生,该算法在这里就不再赘述了,有兴趣的可以自行了解一下。

    2、超时放弃

    当使用synchronized关键词提供的内置锁时,只要线程没有获得锁,那么就会永远等待下去,然而Lock接口提供了boolean tryLock(long time, TimeUnit unit) throws InterruptedException方法,该方法可以按照固定时长等待锁,因此线程可以在获取锁超时以后,主动释放之前已经获得的所有的锁。通过这种方式,也可以很有效地避免死锁。 还是按照之前的例子,时序图如下:

    避免死锁:

    • 预防死锁的几种策略,会严重地损害系统性能。因此在避免死锁时,要施加较弱的限制,从而获得 较满意的系统性能。由于在避免死锁的策略中,允许进程动态地申请资源。因而,系统在进行资源分配之前预先计算资源分配的安全性。若此次分配不会导致系统进入不安全的状态,则将资源分配给进程;否则,进程等待。其中最具有代表性的避免死锁算法是银行家算法。
    • 银行家算法:首先需要定义状态和安全状态的概念。系统的状态是当前给进程分配的资源情况。因此,状态包含两个向量Resource(系统中每种资源的总量)和Available(未分配给进程的每种资源的总量)及两个矩阵Claim(表示进程对资源的需求)和Allocation(表示当前分配给进程的资源)。安全状态是指至少有一个资源分配序列不会导致死锁。当进程请求一组资源时,假设同意该请求,从而改变了系统的状态,然后确定其结果是否还处于安全状态。如果是,同意这个请求;如果不是,阻塞该进程知道同意该请求后系统状态仍然是安全的。

    检测死锁

    1. 首先为每个进程和每个资源指定一个唯一的号码;
    2. 然后建立资源分配表和进程等待表。

    解除死锁:

    当发现有进程死锁后,便应立即把它从死锁状态中解脱出来,常采用的方法有:

    • 剥夺资源:从其它进程剥夺足够数量的资源给死锁进程,以解除死锁状态;
    • 撤消进程:可以直接撤消死锁进程或撤消代价最小的进程,直至有足够的资源可用,死锁状态.消除为止;所谓代价是指优先级、运行代价、进程的重要性和价值等。

    死锁检测

    1、Jstack命令

    jstack是java虚拟机自带的一种堆栈跟踪工具。jstack用于打印出给定的java进程ID或core file或远程调试服务的Java堆栈信息。 Jstack工具可以用于生成java虚拟机当前时刻的线程快照。线程快照是当前java虚拟机内每一条线程正在执行的方法堆栈的集合,生成线程快照的主要目的是定位线程出现长时间停顿的原因,如线程间死锁、死循环、请求外部资源导致的长时间等待等。 线程出现停顿的时候通过jstack来查看各个线程的调用堆栈,就可以知道没有响应的线程到底在后台做什么事情,或者等待什么资源。

    2、JConsole工具

    Jconsole是JDK自带的监控工具,在JDK/bin目录下可以找到。它用于连接正在运行的本地或者远程的JVM,对运行在Java应用程序的资源消耗和性能进行监控,并画出大量的图表,提供强大的可视化界面。而且本身占用的服务器内存很小,甚至可以说几乎不消耗。 --------------------- 本文来自 江溢jonny 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/jonnyhsu_0913/article/details/79633656?utm_source=copy

    参考博文:https://blog.csdn.net/jonnyhsu_0913/article/details/79633656

                     https://blog.csdn.net/sinat_21043777/article/details/53457233

                     https://blog.csdn.net/wsq119/article/details/82218911

     

     

    展开全文
  • 当系统中供多个进程共享的资源如打印机、公用队列的等,其数目不足以满足诸进程的需要时,会引起诸进程对资源的竞争而产生死锁
  • 死锁产生原因和解锁的方法

    万次阅读 2018-10-21 23:14:42
    产生死锁的四个必要条件: (1) 互斥条件:一个资源每次只能被一个进程使用。 (2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。 (3) 不剥夺条件:进程已获得的资源,在末使用完之前...
  • 一、死锁的定义 多进程,多线程的并发执行虽然提升了系统资源的利用率,提高了系统的性能,但是并发...此时称系统处于死锁状态或系统产生死锁,这些永远在互相等待的进程称为死锁进程。 二、几种常见的死锁 1.线程...
  • 什么是数据库死锁? 两个或以上事务同时对一批资源占用锁,并形成循环,就会造成事务死锁,一般报错如下: ... try restarting transaction 1 插入场景:(user_id和pool_id是联合唯一索引) ...
  • 死锁产生原因+如何避免死锁: 一,死锁产生原因: 1)什么是死锁? ​ 所谓死锁,是指多个进程在运行过程中因争夺资源而造成的一种僵局; ​ 当进程处于这种僵持状态,而且无外力作用时,它们都将无法再向...
  • /** *死锁:指两个或者两个以上线程在执行过程中因为争夺资源而造成... *产生原因: * 1系统资源不足 * 2进程运行推进的顺序不合适 * 3资源分配不当 * *解决: * jps命令定位进程号:jps -l * jstack找到死.
  • 主要介绍了mysql 数据库死锁原因及解决办法,需要的朋友可以参考下
  • 本文举例说明SQL Server死锁产生原因,并提出了解决的办法。
  • 死锁产生原因

    2021-06-03 16:51:33
    竞争资源引起进程死锁 可剥夺资源和不可剥夺资源 竞争不可剥夺资源 竞争临时资源
  • SQL死锁产生原因和解决方法

    千次阅读 2020-03-15 10:43:25
    个人博客 死锁现象 表现一:一个用户A 访问表A(锁住了表A),然后又访问表B,另一个用户B 访问表B(锁住了表B),然后...这种死锁是由于你的程序的BUG产生的,除了调整你的程序的逻辑别无他法  仔细分析你程序的逻辑:...
  • 一、死锁的定义: 死锁 :是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。...其次,进程运行推进顺序与速度不同,也可能产生死锁。 ...
  • 产生死锁原因主要是: (1) 因为系统资源不足。 (2) 进程运行推进的顺序不合适。 (3) 资源分配不当等。 产生死锁的四个必要条件: (1)互斥条件:一个资源每次只能被一个进程使用。 (2)请求与保持...
  • 还有一种所谓的临时资源,这是指由一个进程产生,被另一个进程使用,短时间后便无用的资源,故也称为消耗性资源,如硬件中断、信号、消息、缓冲区内的消息等,它也可能引起死锁。例如,SI,S2,S3是临时性资源,进程...
  • SQL Server死锁产生原因及解决办法

    千次阅读 2019-07-15 22:39:29
    其实所有的死锁最深层的原因就是一个:资源竞争  表现一:  一个用户A 访问表A(锁住了表A),然后又访问表B,另一个用户B 访问表B(锁住了表B),然后企图访问表A,这时用户A由于用户B已经锁住表B,它必须等待...
  • 一、什么情况会造成死锁呢? 由于多把互斥锁的使用...方法很简单,加锁的时候只要按照锁的顺序进行加锁即可避免产生死锁情况 三、demo死锁情况 #include <stdio.h> #include <pthread.h> int data = 0
  • 造成死锁原因有如下几条(需同时满足条件): 1、互斥条件:任务使用的资源中至少有一个是不能共享的,资源的使用和释放方法都使用了synchronized关键字修饰 2、至少有一个任务它必须持有一个资源并且这个任务...
  • ⭐️死锁产生的条件 互斥条件:进程要求对所分配的资源进行排它性控制,即在一段时间内某资源仅为一进程所占用。 请求和保持条件:当进程因请求资源而阻塞时,对已获得的资源保持不放。 不剥夺条件:进程已获得的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 98,849
精华内容 39,539
关键字:

死锁产生的原因