Python多任务(4.多线程--Python中的互斥锁和死锁)

互斥锁

1.互斥锁的概念

2.互斥锁的使用

3.使用互斥锁完成2个线程对同一全局变量各加100万次的操作,而不会出现问题

死锁 

死锁的概念

避如何免死锁:

出现死锁的例子


互斥锁

1.互斥锁的概念

  • 互斥锁: 对共享数据进行锁定,保证同一时刻只有一个线程去操作
  • 互斥锁是多个线程一起去抢,抢到锁的线程先执行,没有抢到锁的线程需要等待,等互斥锁使用完释放后,其他等待的线程再去抢这个锁。

2.互斥锁的使用

  • threading模块中定义了Lock变量,这个变量本质上是一个函数,通过调用这个函数可以获取一把互斥锁。

互斥锁使用步骤

  • 创建锁
mutex = threading.Lock()
  • 上锁
mutex.acquire()
'''
''
'
...这里编写代码,能保证同一时刻只能有一个线程去操作,对共享数据进行锁定
  • 释放锁
mutex.release()

注意点:

  • acquire和release方法之间的代码同一时刻只能有一个线程去操作
  • 如果在调用acquire方法的时候,其他线程已经使用了这个互斥锁,那么此时acquire方法会堵塞,直到这个互斥锁释放后才能再次上锁

3.使用互斥锁完成2个线程对同一全局变量各加100万次的操作,而不会出现问题

import threading

# 全局变量
g_num = 0

# 创建互斥锁
lock = threading.Lock()

# 循环100万次执行的任务
def task1():
    # 表示要声明修改全局变量的内存地址
    global g_num

    # 上锁
    lock.acquire()

    # 每循环一次给全局变量加一
    for i in range(1000000):
        g_num += 1

    # 释放锁
    lock.release()
    print("task1: ", g_num)

# 循环100万次执行的任务
def task2():
    # 表示要声明修改全局变量的内存地址
    global g_num

    # 上锁
    lock.acquire()

    # 每循环一次给全局变量加一
    for i in range(1000000):
        g_num += 1

    # 释放锁
    lock.release()

    print("task2: ", g_num)

if __name__ == '__main__':
    first_thread = threading.Thread(target=task1)
    second_thread = threading.Thread(target=task1)

    first_thread.start()
    second_thread.start()

 运行结果: 

  • 互斥锁可以保证同一时刻只有一个线程去执行代码,能够保证全局变量的数据没有问题
  • 线程等待和互斥锁都是把多任务改成单任务去执行,保证了数据的准确性,但是执行性能会下降

死锁 

死锁的概念

  • 死锁: 一直等待对方释放锁的情景就是死锁
  • 死锁是一种状态,有多个互斥锁时,就有可能出现死锁这种状态。
  • 在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁

避如何免死锁:

  1. 程序设计时要尽量避免(银行家算法)     什么是银行家算法?
  2. 添加超时时间等

出现死锁的例子

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

# 创建锁
lock = threading.Lock()


def get_value(index):
    # 上锁
    lock.acquire()

    my_list = [0, 1, 2]
    # 判断下标是否越界
    if index >= len(my_list):
        print("下标越界:", index)
        '''
            如果加上下方代码就不会造成死锁,要把锁给释放掉
            取值不成功,也需要释放互斥锁,不要影响后面的线程去取值
            需要在合适的地方进行释放锁,防止死锁    
            lock.release()        
        '''
        # 这块直接返回了,不执行后面的代码了
        return

        # 根据下标取值
    value = my_list[index]
    print(value)

    # 释放锁
    lock.release()


if __name__ == '__main__':
    for i in range(10):
        sub_thread = threading.Thread(target=get_value, args=(i,))
        sub_thread.start()

 运行结果:  程序一直在执行,一直等待释放锁,这就会造成了死锁

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Python ,可以使用互斥锁(mutex)来实现多线程的互斥操作互斥锁是一种同步原语,它能确保在同一时刻只有一个线程可以进入被保护的临界区。 下面是一个简单的示例,演示了如何使用互斥锁来保护共享资源: ```python import threading # 创建一个互斥锁对象 mutex = threading.Lock() # 共享资源 shared_resource = 0 def increment(): global shared_resource for _ in range(1000000): # 使用互斥锁来保护共享资源 mutex.acquire() shared_resource += 1 mutex.release() def decrement(): global shared_resource for _ in range(1000000): # 使用互斥锁来保护共享资源 mutex.acquire() shared_resource -= 1 mutex.release() # 创建两个线程 t1 = threading.Thread(target=increment) t2 = threading.Thread(target=decrement) # 启动线程 t1.start() t2.start() # 等待线程结束 t1.join() t2.join() print("Shared resource value:", shared_resource) ``` 在上面的示例,我们使用了 `threading.Lock()` 创建了一个互斥锁对象 `mutex`。在 `increment()` 和 `decrement()` 函数,我们使用 `mutex.acquire()` 来获取锁,并使用 `mutex.release()` 来释放锁。这样可以确保在任意时刻只有一个线程可以访问共享资源 `shared_resource`。 请注意,互斥锁是一种比较低级的同步原语,如果使用不当可能会导致死锁等问题。因此,在编写多线程代码时,需要仔细考虑锁的使用方式,以避免潜在的问题。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

还是那个同伟伟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值