精华内容
下载资源
问答
  • 前一篇文章Python:使用threading模块实现多线程编程四[使用Lock互斥锁]我们已经开始...死锁概念所谓死锁指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都...

    前一篇文章Python:使用threading模块实现多线程编程四[使用Lock互斥锁]我们已经开始涉及到如何使用互斥锁来保护我们的公共资源了,现在考虑下面的情况–

    如果有多个公共资源,在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,这会引起什么问题?

    死锁概念

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

    复制代码 代码如下:

    '''

    Created on 2012-9-8

    @author: walfred

    @module: thread.TreadTest5

    '''

    import threading

    counterA = 0

    counterB = 0

    mutexA = threading.Lock()

    mutexB = threading.Lock()

    class MyThread(threading.Thread):

    def __init__(self):

    threading.Thread.__init__(self)

    def run(self):

    self.fun1()

    self.fun2()

    def fun1(self):

    global mutexA, mutexB

    if mutexA.acquire():

    print "I am %s , get res: %s" %(self.name, "ResA")

    if mutexB.acquire():

    print "I am %s , get res: %s" %(self.name, "ResB")

    mutexB.release()

    mutexA.release()

    def fun2(self):

    global mutexA, mutexB

    if mutexB.acquire():

    print "I am %s , get res: %s" %(self.name, "ResB")

    if mutexA.acquire():

    print "I am %s , get res: %s" %(self.name, "ResA")

    mutexA.release()

    mutexB.release()

    if __name__ == "__main__":

    for i in range(0, 100):

    my_thread = MyThread()

    my_thread.start()

    代码中展示了一个线程的两个功能函数分别在获取了一个竞争资源之后再次获取另外的竞争资源,我们看运行结果:

    复制代码 代码如下:

    I am Thread-1 , get res: ResA

    I am Thread-1 , get res: ResB

    I am Thread-2 , get res: ResAI am Thread-1 , get res: ResB

    可以看到,程序已经挂起在那儿了,这种现象我们就称之为”死锁“。

    避免死锁

    避免死锁主要方法就是:正确有序的分配资源,避免死锁算法中最有代表性的算法是Dijkstra E.W 于1968年提出的银行家算法。

    本文标题: Python多线程编程(五):死锁的形成

    本文地址: http://www.cppcns.com/jiaoben/python/122111.html

    展开全文
  • 产生死锁的原因主要:(1) 因为系统资源不足。(2) 进程运行推进的顺序不合适。(3) 资源分配不当等。产生死锁的四个必要条件:(1)互斥条件:一个资源每次只能被一个进程使用。(2)请求与保持条件:一个进程...

    产生死锁的原因主要是:
    (1) 因为系统资源不足。
    (2) 进程运行推进的顺序不合适。
    (3) 资源分配不当等。
    产生死锁的四个必要条件:
    (1)互斥条件:一个资源每次只能被一个进程使用。
    (2)请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
    (3)不可剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
    (4)循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

    避免死锁:
    死锁的预防是通过破坏产生条件来阻止死锁的产生,但这种方法破坏了系统的并行性和并发性。
    死锁产生的前三个条件是死锁产生的必要条件,也就是说要产生死锁必须具备的条件,而不是存在这3个条件就一定产生死锁,那么只要在逻辑上回避了第四个条件就可以避免死锁。
    避免死锁采用的是允许前三个条件存在,但通过合理的资源分配算法来确保永远不会形成环形等待的封闭进程链,从而避免死锁。该方法支持多个进程的并行执行,为了避免死锁,系统动态的确定是否分配一个资源给请求的进程。
    预防死锁:具体的做法是破坏产生死锁的四个必要条件之一。

    银行家算法:该算法需要检查申请者对各类资源的最大需求量,如果现存的各类资源可以满足当前它对各类资源的最大需求量时,就满足当前的申请。换言之,仅当申请者可以在一定时间内无条件归还它所申请的全部资源时,才能把资源分配给它。这样申请者就可以很快完成其计算,然后释放它占用的资源,从而保证了系统中的所有进程都能完成,所以可以避免死锁的发生。这种算法的主要问题是,要求每个进程必须先知道资源的最大需求量,而且在系统的运行过程中,考察每个进程对各类资源的申请需花费较多的时间。另外,这一算法本身也有些保守,因为它总是考虑最坏可能的情况。

    转载于:https://www.cnblogs.com/li-chong/p/3345139.html

    展开全文
  • SQL SERVER如何减少死锁

    2009-11-24 10:34:00
    主要针对SQL Server数据库死锁现象的预防及解决措施进行了详细的介绍,更多内容请大家参考下文: 死锁是指在某组资源中,两个或两个以上的线程在执行过程中,在争夺某一资源时而造成互相等待的现象,若无外力的作用...

     主要针对SQL Server数据库死锁现象的预防及解决措施进行了详细的介绍,更多内容请大家参考下文:
      死锁是指在某组资源中,两个或两个以上的线程在执行过程中,在争夺某一资源时而造成互相等待的现象,若无外力的作用下,它们都将无法推进下去,死时就可能会产生死锁,这些永远在互相等待的进程称为死锁线程。简单的说,进程A等待进程B释放他的资源,B又等待A释放他的资源,这样互相等待就形成死锁。
      如在数据库中,如果需要对一条数据进行修改,首先数据库管理系统会在上面加锁,以保证在同一时间只有一个事务能进行修改操作。如事务1的线程 T1具有表A上的排它锁,事务2的线程T2 具有表B上的排它锁,并且之后需要表A上的锁。事务2无法获得这一锁,因为事务1已拥有它。事务2被阻塞,等待事务1。然后,事务1需要表B的锁,但无法获得锁,因为事务2将它锁定了。事务在提交或回滚之前不能释放持有的锁。因为事务需要对方控制的锁才能继续操作,所以它们不能提交或回滚,这样数据库就会发生死锁了。
      如在编写存储过程的时候,由于有些存储过程事务性的操作比较频繁,如果先锁住表A,再锁住表B,那么在所有的存储过程中都要按照这个顺序来锁定它们。如果无意中某个存储过程中先锁定表B,再锁定表A,这可能就会导致一个死锁。而且死锁一般是不太容易被发现的。
      如果服务器上经常出现这种死锁情况,就会降低服务器的性能,所以应用程序在使用的时候,我们就需要对其进行跟踪,使用sp_who和sp_who2来确定可能是哪些用户阻塞了其他用户,我们还可以用下面的存储过程来跟踪具体的死锁执行的影响:
      
      create procedure sp_who_lock
      as
      begin
      declare @spid int,@bl int,
      @intTransactionCountOnEntry int,
      @intRowcount int,
      @intCountProperties int,
      @intCounter int
      create table #tmp_lock_who (id int identity(1,1),spid smallint,bl smallint)
      IF @@ERROR<>0 RETURN @@ERROR
      insert into #tmp_lock_who(spid,bl) select 0 ,blocked
       from (select * from sysprocesses where blocked>0 ) a
       where not exists(select * from (select * from sysprocesses where blocked>0 ) b
       where a.blocked=spid)
       union select spid,blocked from sysprocesses where blocked>0
      IF @@ERROR<>0 RETURN @@ERROR
      
      -- 找到临时表的记录数
      select @intCountProperties = Count(*),@intCounter = 1
      from #tmp_lock_who
      IF @@ERROR<>0 RETURN @@ERROR
      if @intCountProperties=0
       select '现在没有阻塞和死锁信息' as message
      -- 循环开始
      while @intCounter <= @intCountProperties
      begin
      -- 取第一条记录
       select @spid = spid,@bl = bl
       from #tmp_lock_who where id = @intCounter
      begin
       if @spid =0
       select '引起数据库死锁的是: '+ CAST(@bl AS VARCHAR(10)) + '
      进程号,其执行的SQL语法如下'
      else
       select '进程号SPID:'+ CAST(@spid AS VARCHAR(10))+ '被' + '
      进程号SPID:'+ CAST(@bl AS VARCHAR(10)) +'阻塞,
      其当前进程执行的SQL语法如下'
      DBCC INPUTBUFFER (@bl )
      end
      -- 循环指针下移
      set @intCounter = @intCounter + 1
      end
      drop table #tmp_lock_who
      return 0
      end
      我们只需要通过在查询分析器里面执行sp_who_lock,就可以具体捕捉到执行的堵塞进程,这时我们就可以对对应的SQL语句或者存储过程进行性能上面的改进及设计。
      
      所以我们在数据库设计的时候,虽然不能完全避免死锁,但可以使死锁的数量尽量减少。增加事务的吞吐量并减少系统开销,因为只有很少的事务,所以就得遵循下面的原则:
      按同一顺序访问对象
      如果所有并发事务按同一顺序访问对象,则发生死锁的可能性会降低。在写SQL语句或存储过程的时候,就需要按照顺序在两个并发事务中先获得表A上的锁,然后获得表B上的锁,当第一个事务完成之前,另一个事务被阻塞在表A上。第一个事务提交或回滚后,第二个事务继续进行,而不能在语句里面写先获得表B上的锁,然后再获得表A的锁。
      避免事务中的用户交互
      避免编写包含用户交互的事务,因为运行没有用户交互的批处理的速度要远远快于用户手动响应查询的速度,例如答复应用程序请求参数的提示。例如,如果事务正在等待用户输入,而用户就去做别的事了,则用户将此事务挂起使之不能完成。这样将降低系统的吞吐量,因为事务持有的任何锁只有在事务提交或回滚时才会释放。即使不出现死锁的情况,访问同一资源的其它事务也会被阻塞,等待该事务完成。
      保持事务简短并在一个批处理中
      在同一数据库中并发执行多个需要长时间运行的事务时通常发生死锁。事务运行时间越长,其持有排它锁或更新锁的时间也就越长,从而堵塞了其它活动并可能导致死锁。保持事务在一个批处理中,可以最小化事务的网络通信往返量,减少完成事务可能的延迟并释放锁。
      使用低隔离级别
      确定事务是否能在更低的隔离级别上运行。执行提交读允许事务读取另一个事务已读取(未修改)的数据,而不必等待第一个事务完成。使用较低的隔离级别(例如提交读)而不使用较高的隔离级别(例如可串行读)可以缩短持有共享锁的时间,从而降低了锁定争夺。
      使用绑定连接
      使用绑定连接使同一应用程序所打开的两个或多个连接可以相互合作。次级连接所获得的任何锁可以象由主连接获得的锁那样持有,反之亦然,因此不会相互阻塞。
      下面有一些对死锁发生的一些建议:
      (1)对于频繁使用的表使用集簇化的索引;
      (2)设法避免一次性影响大量记录的T-SQL语句,特别是INSERT和UPDATE语句;
      (3)设法让UPDATE和DELETE语句使用索引;
      (4)使用嵌套事务时,避免提交和回退冲突;
      (5)对一些数据不需要及时读取更新值的表在写SQL的时候在表后台加上(nolock),如:Select * from tableA(nolock)

    展开全文
  •  7、锁或者死锁(这也查询慢常见的问题,程序设计的缺陷)   8、sp_lock,sp_who,活动的用户查看,原因读写竞争资源。   9、返回了不必要的行和列   10、查询语句不好,没有优化  可以通过如下...
  • 死锁是指在某组资源中,两个或两个以上的线程在执行过程中,在争夺某一资源时而造成互相等待的现象,若无外力的作用下,它们都将无法推进下去,死时就可能会产生死锁,这些永远在互相等待的进程称为死锁线程。...
    死锁是指在某组资源中,两个或两个以上的线程在执行过程中,在争夺某一资源时而造成互相等待的现象,若无外力的作用下,它们都将无法推进下去,死时就可能会产生死锁,这些永远在互相等待的进程称为死锁线程。简单的说,进程A等待进程B释放他的资源,B又等待A释放他的资源,这样互相等待就形成死锁。

      如在数据库中,如果需要对一条数据进行修改,首先数据库管理系统会在上面加锁,以保证在同一时间只有一个事务能进行修改操作。如事务1的线程 T1具有表A上的排它锁,事务2的线程T2 具有表B上的排它锁,并且之后需要表A上的锁。事务2无法获得这一锁,因为事务1已拥有它。事务2被阻塞,等待事务1。然后,事务1需要表B的锁,但无法获得锁,因为事务2将它锁定了。事务在提交或回滚之前不能释放持有的锁。因为事务需要对方控制的锁才能继续操作,所以它们不能提交或回滚,这样数据库就会发生死锁了。

      如在编写存储过程的时候,由于有些存储过程事务性的操作比较频繁,如果先锁住表A,再锁住表B,那么在所有的存储过程中都要按照这个顺序来锁定它们。如果无意中某个存储过程中先锁定表B,再锁定表A,这可能就会导致一个死锁。而且死锁一般是不太容易被发现的。

      如果服务器上经常出现这种死锁情况,就会降低服务器的性能,所以应用程序在使用的时候,我们就需要对其进行跟踪,使用sp_who和sp_who2来确定可能是哪些用户阻塞了其他用户,我们还可以用下面的存储过程来跟踪具体的死锁执行的影响:

    create  procedure sp_who_lock

    as

    begin

    declare @spid int,@bl int,

            @intTransactionCountOnEntry  int,

            @intRowcount    int,

            @intCountProperties   int,

            @intCounter    int 

     create table #tmp_lock_who (id int identity(1,1),spid smallint,bl smallint)

     IF @@ERROR<>0 RETURN @@ERROR

     insert into #tmp_lock_who(spid,bl) select  0 ,blocked

       from (select * from sysprocesses where  blocked>0 ) a 

       where not exists(select * from (select * from sysprocesses where  blocked>0 ) b 

       where a.blocked=spid)

       union select spid,blocked from sysprocesses where  blocked>0

     IF @@ERROR<>0 RETURN @@ERROR 

    -- 找到临时表的记录数

     select  @intCountProperties = Count(*),@intCounter = 1

     from #tmp_lock_who

     IF @@ERROR<>0 RETURN @@ERROR 

     if @intCountProperties=0

      select '现在没有阻塞和死锁信息' as message

    -- 循环开始

    while @intCounter <= @intCountProperties

    begin

    -- 取第一条记录

      select  @spid = spid,@bl = bl

      from #tmp_lock_who where id = @intCounter 

     begin

      if @spid =0 

        select '引起数据库死锁的是: '+ CAST(@bl AS VARCHAR(10)) + '进程号,其执行的SQL语法如下'

     else

        select '进程号SPID:'+ CAST(@spid AS VARCHAR(10))+ '被' + '进程号SPID:'+ CAST(@bl AS VARCHAR(10)) +'阻塞,其当前进程执行的SQL语法如下'

     DBCC INPUTBUFFER (@bl )

     end 

    -- 循环指针下移

     set @intCounter = @intCounter + 1

    end

    drop table #tmp_lock_who

    return 0

    end

    我们只需要通过在查询分析器里面执行sp_who_lock,就可以具体捕捉到执行的堵塞进程,这时我们就可以对对应的SQL语句或者存储过程进行性能上面的改进及设计。

      所以我们在数据库设计的时候,虽然不能完全避免死锁,但可以使死锁的数量尽量减少。增加事务的吞吐量并减少系统开销,因为只有很少的事务,所以就得遵循下面的原则:

      按同一顺序访问对象

      如果所有并发事务按同一顺序访问对象,则发生死锁的可能性会降低。在写SQL语句或存储过程的时候,就需要按照顺序在两个并发事务中先获得表A上的锁,然后获得表B上的锁,当第一个事务完成之前,另一个事务被阻塞在表A上。第一个事务提交或回滚后,第二个事务继续进行,而不能在语句里面写先获得表B上的锁,然后再获得表A的锁。
      避免事务中的用户交互

      避免编写包含用户交互的事务,因为运行没有用户交互的批处理的速度要远远快于用户手动响应查询的速度,例如答复应用程序请求参数的提示。例如,如果事务正在等待用户输入,而用户就去做别的事了,则用户将此事务挂起使之不能完成。这样将降低系统的吞吐量,因为事务持有的任何锁只有在事务提交或回滚时才会释放。即使不出现死锁的情况,访问同一资源的其它事务也会被阻塞,等待该事务完成。

      保持事务简短并在一个批处理中

      在同一数据库中并发执行多个需要长时间运行的事务时通常发生死锁。事务运行时间越长,其持有排它锁或更新锁的时间也就越长,从而堵塞了其它活动并可能导致死锁。保持事务在一个批处理中,可以最小化事务的网络通信往返量,减少完成事务可能的延迟并释放锁。

      使用低隔离级别

      确定事务是否能在更低的隔离级别上运行。执行提交读允许事务读取另一个事务已读取(未修改)的数据,而不必等待第一个事务完成。使用较低的隔离级别(例如提交读)而不使用较高的隔离级别(例如可串行读)可以缩短持有共享锁的时间,从而降低了锁定争夺。

      使用绑定连接

      使用绑定连接使同一应用程序所打开的两个或多个连接可以相互合作。次级连接所获得的任何锁可以象由主连接获得的锁那样持有,反之亦然,因此不会相互阻塞。

      下面有一些对死锁发生的一些建议:


      1)对于频繁使用的表使用集簇化的索引;

      2)设法避免一次性影响大量记录的T-SQL语句,特别是INSERT和UPDATE语句;

      3)设法让UPDATE和DELETE语句使用索引;

      4)使用嵌套事务时,避免提交和回退冲突;

      5)对一些数据不需要及时读取更新值的表在写SQL的时候在表后台加上(nolock),如:Select * from tableA(nolock)

    展开全文
  • 【IT168 技术文档】死锁是指在某组资源中,两个或两个以上的线程在执行过程中,在争夺某一资源时而造成互相等待的现象,若无外力的作用下,它们都将无法推进下去,死时就可能会产生死锁,这些永远在互相等待的进程称为...
  • 查询速度慢的原因很多,常见如下几种: 1、没有索引或者没有用到索引(这查询慢最常见的问题,程序设计的缺陷) 2、I/O吞吐量小,形成了...7、锁或者死锁(这也查询慢最常见的问题,程序设计的缺陷) ...
  • SQL Server数据库查询速度慢的原因有很多,常见的有以下几种:  1、没有索引或者没有用到索引(这查询慢最常见的问题,程序设计的缺陷)  2、I/O吞吐量小,形成... 7、锁或者死锁(这也查询慢最常见的问题,...
  • [转载] 1、没有索引或者没有用到索引(这查询慢最常见的问题,程序设计的缺陷) 2、I/O吞吐量小,形成了瓶颈效应。...7、锁或者死锁(这也查询慢最常见的问题,程序设计的缺陷) 8、sp_lock,sp_...
  • 如何优化SQL Server数据库查询(三)

    千次阅读 2008-04-10 22:07:00
    优化SQL Server数据库 查询速度慢的原因很多,常见如下几种: 1、没有索引或者没有用到索引(这查询慢最常见的问题,程序设计的缺陷) 2、I/O吞吐量小,形成了瓶颈效应。 3、没有创建计算列导致查询不优化。 ...
  • 1SQLServer数据库查询速度慢的原因有很多,常见的有以下几种:1、没有索引或者没有用到索引(这查询慢最常见的问题,程序设计的缺陷)2、I/O吞吐量小,形成了瓶颈效应。3、没有创建计算列导致查询不优化。4、内存...

空空如也

空空如也

1 2 3
收藏数 44
精华内容 17
关键字:

数据库死锁是如何形成