精华内容
下载资源
问答
  • python死锁

    2019-03-21 11:53:04
    一、死锁原理: (1)在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁。 (2)产生死锁的四个必要条件: ①互斥条件:一个资源只能被一个进程使用; ②请求与保持...

    一、死锁原理:

    (1)在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁。
    (2)产生死锁的四个必要条件:
    ①互斥条件:一个资源只能被一个进程使用;
    ②请求与保持条件:一个进程因请求资源而阻塞时,对方已获得的资源不释放。
    ③不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺。
    ④循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

    二:避免死锁:
    (1)资源的访问要有序
    (2)减少资源占有时间

    展开全文
  • python 死锁

    2019-01-18 09:05:59
    一、死锁原理: (1)在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁。 (2)产生死锁的四个必要条件: ①互斥条件:一个资源只能被一个进程使用; ②请求与保持...

    一、死锁原理:

    (1)在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁。
    (2)产生死锁的四个必要条件:
    ①互斥条件:一个资源只能被一个进程使用;
    ②请求与保持条件:一个进程因请求资源而阻塞时,对方已获得的资源不释放。
    ③不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺。
    ④循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

    二:避免死锁:
    (1)资源的访问要有序
    (2)减少资源占有时间

    展开全文
  • python死锁学习

    2020-03-02 22:06:17
    本文对Python死锁文章进行总结,对部分难以理解内容做了解释。 首先先列举一个会发生死锁的情况 死锁的一个原因是互斥锁。假设银行系统中,用户a试图转账100块给用户b, 与此同时用户b试图转账200块给用户a,则可能...

    举例

    本文对Python死锁文章进行总结,对部分难以理解内容做了解释。
    首先先列举一个会发生死锁的情况

    死锁的一个原因是互斥锁。假设银行系统中,用户a试图转账100块给用户b,
    与此同时用户b试图转账200块给用户a,则可能产生死锁。
    2个线程互相等待对方的锁,互相占用着资源不释放。
    #coding=utf-8
    import time
    import threading
    class Account:
      def __init__(self, _id, balance, lock):
        self.id = _id
        self.balance = balance
        self.lock = lock
    
      def withdraw(self, amount):
        self.balance -= amount
    
      def deposit(self, amount):
        self.balance += amount
    
    
    def transfer(_from, to, amount):
      if _from.lock.acquire():#锁住自己的账户
        _from.withdraw(amount)
        time.sleep(1)#让交易时间变长,2个交易线程时间上重叠,有足够时间来产生死锁
        print('wait for lock...')
        if to.lock.acquire():#锁住对方的账户
          to.deposit(amount)
          to.lock.release()
        _from.lock.release()
      print( 'finish...')
    
    a = Account('a',1000, threading.Lock())
    b = Account('b',1000, threading.Lock())
    threading.Thread(target = transfer, args = (a, b, 100)).start()
    threading.Thread(target = transfer, args = (b, a, 200)).start()
    

    在多线程程序中,死锁问题很大一部分是由于线程同时获取多个锁造成的。举个例子:一个线程获取了第一个锁,然后在获取第二个锁的 时候发生阻塞,那么这个线程就可能阻塞其他线程的执行,从而导致整个程序假死。 解决死锁问题的一种方案是为程序中的每一个锁分配一个唯一的id,然后只允许按照升序规则来使用多个锁,这个规则使用上下文管理器 是非常容易实现的

    先来看一下什么是上下文管理器@contextmanager
    被装饰器装饰的函数分为三部分:

    1. with语句中的代码块执行前执行函数中yield之前代码
    2. yield返回的内容复制给as之后的变量
    3. with代码块执行完毕后执行函数中yield之后的代码

    解决方案

    import threading
    from contextlib import contextmanager
    
    # Thread-local state to stored information on locks already acquired
    _local = threading.local()
    
    
    @contextmanager
    def acquire(*locks):
      # Sort locks by object identifier
      locks = sorted(locks, key=lambda x: id(x))
    
      # Make sure lock order of previously acquired locks is not violated
      acquired = getattr(_local, 'acquired', [])
      #如果出现新锁id大于旧锁id 报错
      if acquired and max(id(lock) for lock in acquired) >= id(locks[0]):
        raise RuntimeError('Lock Order Violation')
      # Acquire all of the locks
      acquired.extend(locks)
      _local.acquired = acquired
      try:
        for lock in locks:
          lock.acquire()
        yield		#无返回值 yield为空
      finally:
        # Release locks in reverse order of acquisition
        for lock in reversed(locks):
          lock.release()
        del _local.acquired[-len(locks):]
    

    当然采用升序获取锁也存在一定的问题,看下列代码

    import threading
    x_lock = threading.Lock()
    y_lock = threading.Lock()
     
    def thread_1():
      while True:
            with acquire(x_lock):
                print("acquire x_lock")
                time.sleep(1)
                with acquire(y_lock):
                    print('Thread-1')
                    time.sleep(1)
    
    
    def thread_2():
      while True:
            with acquire(y_lock):
                print('acquire y_lock')
                time.sleep(1)
                with acquire(x_lock):
                    print('Thread-2')
     
    t1 = threading.Thread(target=thread_1)
    t1.daemon = False
    t1.start()
     
    t2 = threading.Thread(target=thread_2)
    t2.daemon = False
    t2.start()
    
    daemon:
    (1)如果某个子线程的daemon属性为False,主线程结束时会检测该子线程是否结束,
    如果该子线程还在运行,则主线程会等待它完成后再退出;
    (2)如果某个子线程的daemon属性为True,主线程运行结束时不对这个子线程进行检
    查而直接退出,同时所有daemon值为True的子线程将随主线程一起结束,而不论
    是否运行完成。
    
    

    代码运行结果为出现异常
    在这里插入图片描述
    发生崩溃的原因在于,每个线程都记录着自己已经获取到的锁。 acquire() 函数会检查之前已经获取的锁列表, 由于锁是按照升序排列获取的,所以函数会认为之前已获取的锁的id必定小于新申请到的锁,这时就会触发异常。
    出现上述结果的原因是异常先出现在Thread-2,导致该线程中断。之后不会发生死锁现象了,因为只有一个线程Thread-1在运行,并且通过上下文管理器,每次内部acquire调用完毕后会自动释放锁,所以不会出现死锁现象了。

    总结:

    避免死锁是一种解决死锁问题的方式,在进程获取锁的时候会严格按照对象id升序排列获取,经过数学证明,这样保证程序不会进入 死锁状态。避免死锁的主要思想是,单纯地按照对象id递增的顺序加锁不会产生循环依赖,而循环依赖是 死锁的一个必要条件,从而避免程序进入死锁状态。

    展开全文
  • 死锁 死锁: 死锁就是一直等待对方释放锁的情景 死锁的结果会造成程序的停止响应, 不能再处理其他的任务了 死锁的示例 需求: 根据下标在列表中取值, 保证同一时刻只能有一个线程去取值 import threading import ...

    死锁

    1. 死锁: 死锁就是一直等待对方释放锁的情景
    2. 死锁的结果会造成程序的停止响应, 不能再处理其他的任务了

    死锁的示例

    需求: 根据下标在列表中取值, 保证同一时刻只能有一个线程去取值

    import threading
    import time
    
    #创建互斥锁
    lock = threading.Lock()
    
    # 根据下标去取值, 保证同一时刻只有一个线程去取值
    def get_value(index):
    	
    	# 上锁
    	lock.acquire()
    	print(threading.current_thread())
    	my_list = [3, 6, 8, 1]
    	# 判断下标释放越界
    	if index >= len(my_list):
    		print("下标越界", index)
    		return
    	value = my_list[index]
    	print("value", value)
    	time.sleep(0.2)
    	# 释放锁
    	lock.release()
    
    
    if __name__ == "__main__":
    	# 模拟大量线程去执行操作
    	for i in range(30):
    		sub_thread = threading.Thread(target=get_value, args=(i,))
    		sub_thread.start()
    
    # 控制台输出
    <Thread(Thread-1, started 10400)>
    value 3
    <Thread(Thread-2, started 568)>
    value 6
    <Thread(Thread-3, started 6360)>
    value 8
    <Thread(Thread-4, started 13328)>
    value 1
    <Thread(Thread-5, started 3012)>
    下标越界 4
    
    
    # 此刻程序还未结束
    

    避免死锁

    避免死锁就要在合适的地方释放锁

    import threading
    import time
    
    # 创建互斥锁
    lock = threading.Lock()
    
    # 根据下标去取值, 保证在同一时刻只能有一个线程取值
    def get_value(index):
    	
    	lock.acquire()
    	print(threading.surrrent_thred())
    	my_list = [3, 6, 8, 1]
    	if index >= len(my_list):
    		print("下标越界", index)
    		# 当下标越界需要释放释放锁, 让后边的线程还可以取值
    		lock.release()
    		return
    	value = my_list[index]
    	print(value)
    	time.sleep(0.2)
    	lock.release()
    
    
    if __name__ == "__main__":
    	# 模拟大量线程去执行取值操作
    	for i in range(30):
    		sub_thread = threading.Thread(target=get_value, args=(i,))
    		sub_thread.start()
    
    		
    #  控制台输出 <没有产生死锁>
    <Thread(Thread-1, started 14704)>
    3
    <Thread(Thread-2, started 11788)>
    6
    <Thread(Thread-3, started 1220)>
    8
    <Thread(Thread-4, started 15180)>
    1
    <Thread(Thread-5, started 11204)>
    下标越界 4
    <Thread(Thread-6, started 12608)>
    ...
    <Thread(Thread-29, started 9496)>
    下标越界 28
    <Thread(Thread-30, started 12456)>
    下标越界 29
    

    个人见解,仅供参考
    刚才在写避免死锁的程序时, 突然奇想想用 with 试试, 试完之后发现 with 能巧妙地避开这个死锁的问题.然后大胆想象了一下, with 是不是能避免死锁, 就百度找了下文章. 发现 python中确实可以用 with 避免死锁

    import threading
    import time
    
    # 创建互斥锁
    lock = threading.Lock()
    
    # 根据下标去取值, 保证同一时刻只能有一个线程去取值
    
    
    def get_value(index):
    	# with 自己上锁, 并自己释放锁
    	with lock:
    		print(threading.current_thread())
    		my_list = [3, 6, 8, 1]
    		if index >= len(my_list):
    			print("下标越界", index)
    			return
    		value = my_list[index]
    		print(value)
    		time.sleep(0.2)
    
    
    if __name__ == "__main__":
    	# 模拟大量线程去执行取值操作
    	for i in range(30):
    		sub_thread = threading.Thread(target=get_value, args=(i,))
    		sub_thread.start()
    

    小结

    1. 使用互斥锁的时候需要注意死锁的问题, 要在合适的地方注意释放锁
    2. 死锁一旦产生就会造成应用程序的停止响应, 应用程序无法再继续往下执行了
    3. with 可以避免上边的问题, 个人见解
    展开全文
  • Python死锁的形成

    2015-04-05 16:40:18
    Python死锁是怎么形成的呢?死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待...
  • Python死锁问题查找

    千次阅读 2014-02-05 20:28:48
    1 用Python写的程序,由于其GIL的存在,死锁的情况变得有点复杂。 2 基本上可以分成两种情况: 一种是在调用Thread.join,Queue.put,Queue.get,Rock.acquire这些函数造成的死锁,可以归结成Python代码层造成的死锁 另...
  • #!/usr/bin/env python import threading import time class MyThread(threading.Thread): def do1(self): global resA,resB if mutexA.acquire():
  • #死锁 ''' 开发过程中使用线程,在线程间共享多个资源的时候, 如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁。 尽管死锁很少发生,但一旦发生就会造成应用的停止响应,程序不做任何事情。...
  • 前言 这几年一直在it行业里摸爬滚打,一路走来,不少总结了一些python行业里的高频面试,看到大部分初入行的新鲜血液,还在为各样的面试题答案或收录有各种困难问题 ...死锁 不合理的同步方式,将会
  • Python死锁与递归锁

    2018-03-09 16:19:00
    Lock() 互斥锁会导致死锁,用RLock()递归锁代替。 递归锁:可以连续acquire多次,每acquire一次计数器+1(无论acquire的是哪个锁),只有计数为0才能被acquire mutexB = mutexA = RLock() class MyThread...
  • 何谓死锁 # 所谓死锁: 是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象, # 若无外力作用,它们都将无法推进...# 在Python中为了支持在同一线程中多次请求同一资源,python...
  • 1. 死锁与递归锁 1.1 死锁 当你知道锁的使用抢锁必须要释放锁,其实你在操作锁的时候也极其容易产生死锁现象(整个程序卡死 阻塞) from threading import Thread, Lock import time mutexA = Lock() mutexB = ...
  • 目录:一 死锁二 递归锁三 信号量四 Event事件 一 死锁 """ 了解 当你知道锁的使用抢锁时必须要释放锁,也容易产生死锁现象 单例模式-----? """ # from threading import Thread, Lock # import time # # 类只要多...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 20,083
精华内容 8,033
关键字:

python死锁

python 订阅