python多线程互斥锁与死锁

目录
  • 一、多线程间的资源竞争
  • 二、互斥锁
    • 1.互斥锁示例
    • 2.可重入锁与不可重入锁
  • 三、死锁

一、多线程间的资源竞争

以下列task1()task2()两个函数为例,分别将对全局变量num加一重复一千万次循环(数据大一些,太小的话执行太快,达不到验证的效果)。

import threading
import time

num = 0

def task1(nums):
    global num
    for i in range(nums):
        num += 1

    print("task1---num=%d" % num)

def task2(nums):
    global num
    for i in range(nums):
        num += 1
    print("task2---num=%d" % num)

if __name__ == '__main__':
    nums = 10000000
    t1 = threading.Thread(target=task1, args=(nums,))
    t2 = threading.Thread(target=task2, args=(nums,))

    t1.start()
    t2.start()
    # 因为主线程不会等子线程执行完就会执行,所以这里延迟五秒,确保最后执行。
    time.sleep(5)
    print("main----num=%d" % num)

程序运行结果:

如图,输出结果比较混乱,既没有一千万,最终结果也不是二千万。因为多线程运行时出现了资源竞争,即可以理解为,每个函数运行的时间都不确定,且互相影响,
如从初始值0开始,假设t1的线程先执行,执行到+1后,此时的num=1还未存储,然后即被叫停,t2开始执行,去获取num,获取到的num等于初始值0,然后其执行了+1并存储,存储后num=1,然后t2停止t1继续,再次存储num=1。即加了两次1,但是num还是只等于1。
因为t1和t2谁来运行的分配是完全随机的,所以最后加了两千万次1后值是小于2000万的。

解决此类问题,可以使用到互斥锁 。

二、互斥锁

  • 某个线程要更改共享数据时,先将其锁定,此时资源的状态为"锁定",其他线程不能改变,只到该线程释放资源,将资源的状态变成"非锁定",其他的线程才能再次锁定该资源。
  • 互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。

1.互斥锁示例

创建一把锁:

mutex = threading.Lock()
mutex.acquire() # 上锁
xxxx锁定的内容xxxxx
mutex.release() # 解锁

将互斥锁加入到上边的代码中如下,则问题得到了解决。

import threading
import time

num = 0

def task1(nums):
    global num
    mutex.acquire()
    for i in range(nums):
        num += 1
    mutex.release()
    print("task1---num=%d" % num)

def task2(nums):
    global num
    mutex.acquire()
    for i in range(nums):
        num += 1
    mutex.release()
    print("task2---num=%d" % num)

if __name__ == '__main__':
    nums = 10000000
    mutex = threading.Lock()
    t1 = threading.Thread(target=task1, args=(nums,))
    t2 = threading.Thread(target=task2, args=(nums,))

    t1.start()
    t2.start()
    # 因为主线程不会等子线程执行完就会执行,所以这里延迟五秒,确保最后执行。
    time.sleep(5)
    print("main----num=%d" % num)

程序运行结果:

2.可重入锁与不可重入锁

threading.Lock()上的是不可重入锁,即一次只能加一把锁,不能加多把。

threading.Lock()

如果需要同时加多把所,则需加入不可重入锁

创建一把可重入锁:

mutex = threading.RLock()
mutex.acquire() # 上锁
mutex.acquire() # 再上锁
xxxx锁定的内容xxxxx
mutex.release() # 解锁
mutex.release() # 再解锁

其中上锁和解锁的次数必须保持一致。

三、死锁

在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会程序堵塞,造成死锁。

  • 死锁一般用不到。
  • 程序设计要尽量避免。

到此这篇关于python多线程互斥锁与死锁的文章就介绍到这了,更多相关python多线程互斥锁与死锁内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • python多线程互斥锁与死锁问题详解

    目录 一.多线程共享全局变量 二.给线程加一把锁锁 三.死锁问题 总结 一.多线程共享全局变量 代码实现的功能: 创建work01与worker02函数,对全局变量进行加一操作创建main函数,生成两个线程,同时调用两个函数 代码如下: import threading result = 0 # 定义全局变量result def work1(num): global result for i in range(num): result += 1 print('------from work1--

  • python多线程互斥锁与死锁

    目录 一.多线程间的资源竞争 二.互斥锁 1.互斥锁示例 2.可重入锁与不可重入锁 三.死锁 一.多线程间的资源竞争 以下列task1(),task2()两个函数为例,分别将对全局变量num加一重复一千万次循环(数据大一些,太小的话执行太快,达不到验证的效果). import threading import time num = 0 def task1(nums):     global num     for i in range(nums):         num += 1     pr

  • C++多线程之互斥锁与死锁

    目录 1.前言 2.互斥锁 2.1 互斥锁的特点 2.2 互斥锁的使用 2.3 std::lock_guard 3.死锁 3.1 死锁的含义 3.2 死锁的例子 3.3 死锁的解决方法 1.前言 比如说我们现在以一个list容器来模仿一个消息队列,当消息来临时插入list的尾部,当读取消息时就把头部的消息读出来并且删除这条消息.在代码中就以两个线程分别实现消息写入和消息读取的功能,如下: class msgList { private: list<int>mylist; //用list模仿一个

  • python多线程高级锁condition简单用法示例

    本文实例讲述了python多线程高级锁condition简单用法.分享给大家供大家参考,具体如下: 多线程编程中如果使用Condition对象代替lock, 能够实现在某个事件触发后才处理数据, condition中含有的方法: - wait:线程挂起,收到notify通知后继续运行 - notify:通知其他线程, 解除其它线程的wai状态 - notifyAll(): 通知所有线程 - acquire和release: 获得锁和解除锁, 与lock类似, - enter和exit使得对象支持

  • 详解python多线程、锁、event事件机制的简单使用

    线程和进程 1.线程共享创建它的进程的地址空间,进程有自己的地址空间 2.线程可以访问进程所有的数据,线程可以相互访问 3.线程之间的数据是独立的 4.子进程复制线程的数据 5.子进程启动后是独立的 ,父进程只能杀掉子进程,而不能进行数据交换 6.修改线程中的数据,都是会影响其他的线程,而对于进程的更改,不会影响子进程 threading.Thread Thread 是threading模块中最重要的类之一,可以使用它来创建线程.有两种方式来创建线程:一种是通过继承Thread类,重写它的run

  • Python的互斥锁与信号量详解

    并发与锁 多个线程共享数据的时候,如果数据不进行保护,那么可能出现数据不一致现象,使用锁,信号量.条件锁 互斥锁 1. 互斥锁,是使用一把锁把代码保护起来,以牺牲性能换取代码的安全性,那么Rlock后 必须要relase 解锁 不然将会失去多线程程序的优势 2. 互斥锁的基本使用规则: import threading # 声明互斥锁 lock=threading.Rlock(); def handle(sid):# 功能实现代码 lock.acquire() #加锁 # writer code

  • C++多线程互斥锁和条件变量的详解

    目录 互斥锁: std::mutex::try_lock 条件变量:condition_variable 总结 我们了解互斥量和条件变量之前,我们先来看一下为什么要有互斥量和条件变量这两个东西,了解为什么有这两东西之后,理解起来后面的东西就简单很多了!!! 先来看下面这段简单的代码: int g_num = 0; void print(int id) { for (int i = 0; i < 5; i++) { ++g_num; cout << "id = " &l

  • 浅析Linux下一个简单的多线程互斥锁的例子

    复制代码 代码如下: #include <stdio.h>#include <pthread.h>pthread_mutex_t Device_mutex ;int count=0;void thread_func1(){   while(1)   {       pthread_mutex_lock(&Device_mutex);       printf("thread1: %d\n",count);       pthread_mutex_unlo

  • 举例讲解Python中的死锁、可重入锁和互斥锁

    一.死锁 简单来说,死锁是一个资源被多次调用,而多次调用方都未能释放该资源就会造成死锁,这里结合例子说明下两种常见的死锁情况. 1.迭代死锁 该情况是一个线程"迭代"请求同一个资源,直接就会造成死锁: import threading import time class MyThread(threading.Thread): def run(self): global num time.sleep(1) if mutex.acquire(1): num = num+1 msg = se

  • Python多线程编程(四):使用Lock互斥锁

    前面已经演示了Python:使用threading模块实现多线程编程二两种方式起线程和Python:使用threading模块实现多线程编程三threading.Thread类的重要函数,这两篇文章的示例都是演示了互不相干的独立线程,现在我们考虑这样一个问题:假设各个线程需要访问同一公共资源,我们的代码该怎么写? 复制代码 代码如下: ''' Created on 2012-9-8   @author: walfred @module: thread.ThreadTest3 '''  impor

随机推荐