Python Lock 死锁问题

1.1死锁发生的必要条件
在这里插入图片描述
在这里插入图片描述1.2.1死锁例子 简单模拟银行转账

"""
    银行转账
"""

from time import sleep
from threading import Thread,Lock

# 账户类
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 get_balance(self):
        return self.balance

# 产生两个账户
Tom = Account('Tom', 5000, Lock())
Alex = Account('Alex', 8000, Lock())

# 转账过程
def transfer(from_, to, amount):
    if from_.lock.acquire():    # 锁住自己的账户
        from_.withdraw(amount)
        sleep(0.5)
        if to.lock.acquire():   # 锁住自己的账户
            to.deposit(amount)  # to账户加钱
            to.lock.release()   # to账户解锁
        from_.lock.release()    # from账户解锁
    print("%s给%s转账%d"%(from_.id, to.id, amount))

t1 = Thread(target = transfer, args = (Tom, Alex, 2000))
t2 = Thread(target = transfer, args = (Alex, Tom, 1000))
t1.start()
t2.start()

运行结果:执行两个线程就会形成死锁
解锁位置不对
from_, to 独立进行 解锁并上锁则不会出现死锁现象

1.2.2正确代码

"""
    死锁例子
    银行转账
"""

from time import sleep
from threading import Thread,Lock

# 账户类
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 get_balance(self):
        return self.balance

# 产生两个账户
Tom = Account('Tom', 5000, Lock())
Alex = Account('Alex', 8000, Lock())

# 转账过程
def transfer(from_, to, amount):
    if from_.lock.acquire():    # 锁住自己的账户
        from_.withdraw(amount)
        sleep(0.5)
        from_.lock.release()  # from账户解锁
        if to.lock.acquire():   # 锁住自己的账户
            to.deposit(amount)  # to账户加钱
            to.lock.release()   # to账户解锁
    print("%s给%s转账%d"%(from_.id, to.id, amount))

t1 = Thread(target = transfer, args = (Tom, Alex, 2000))
t2 = Thread(target = transfer, args = (Alex, Tom, 1000))
t1.start()
t2.start()

运行结果:
Alex给Tom转账1000
Tom给Alex转账2000

Process finished with exit code 0

在这里插入图片描述
1.3 案例分析

"""
    模拟迅雷下载文件
    一个文件放在几个不同位置 要求从每个分文件下载1/n 到一个新文件中 同步进行下载
"""

from threading import Thread, Lock
import os

lock = Lock()
urls = ['/home/tarena/桌面']  # 自定义多个路径列表
filename = input("要下载的文件:")
explorer = []
for i in urls:
    if os.path.exists(i + filename):
        explorer.append(i + filename)
path_num = len(explorer)

if path_num == 0:
    os._exit(0)

file_size = os.path.getsize(explorer[0])    # 获得要下载文件大小
block_size = file_size//path_num    # 根据需处理文件数确定一个线程下载的数量
fd = open(filename,'wb')

def load(path, num):
    f = open(path, 'rb')
    seek_num = block_size * (num - 1)
    f.seek(seek_num)
    data = f.read(block_size)   # 模拟下载过程
    with lock:
        fd.seek(seek_num)
        fd.write(data)

num = 0
jobs = []
for path in explorer:
    t = Thread(target=load, args=(path, num))
    jobs.append(t)
    t.start()
    num += 1
    
for i in jobs:
    i.join()
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python中的lock()是用于解决线程安全问题的一种机制。它可以防止多个线程同时访问共享资源导致的竞争问题。引用和引用中提供了两种使用lock()的方式。在引用中,使用了RLock(),它是一种递归,支持多次定。而在引用中,使用了with语句来自动管理。无论是使用RLock()还是Lock(),都需要在代码中使用acquire()方法来获取,并在完成后使用release()方法释放。在使用lock时,需要注意避免出现的情况,即多个线程同时竞争获取同一个的情况。为了避免,我们可以使用try-finally语句来确保的释放。下面是一个使用lock的示例代码: ```python import threading lock = threading.Lock() def test(): lock.acquire() try: for i in range(3): print(threading.current_thread().name, i) time.sleep(1) finally: lock.release() for i in range(2): threading.Thread(target=test).start() ``` 在上面的代码中,我们首先创建了一个Lock对象,然后定义了一个test函数,在函数中使用acquire()方法获取,然后执行一段需要保护的代码,最后使用release()方法释放。我们使用Thread类创建了两个线程,并分别启动了这两个线程来执行test函数。这样,我们就实现了对共享资源的线程安全访问。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [python使用lock](https://blog.csdn.net/SongRgg/article/details/8349389)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [python多线程系列—Lock(三)](https://blog.csdn.net/weixin_54542209/article/details/126159199)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值