猪行天下之Python基础——9.2 Python多线程与多进程(中)(一)

简介: 内容简述:1、threading模块详解2、queue模块详解

1、threading模块详解


Python提供的与线程操作相关的模块,网上有很多资料还是用的thread模块,在3.x版本中已经使用threading来替代thread,如果你在python 2.x版本想使用threading的话,可以使用dummy_threading模块


① threading模块提供的可直接调用的函数


  • active_count():获取当前活跃(alive)线程的个数。


  • current_thread():获取当前的线程对象。


  • get_ident():返回当前线程的索引,一个非零的整数(3.3新增)。


  • enumerate():获取当前所有活跃线程的列表。


  • main_thread():返回主线程对象(3.4新增)。


  • settrace(func):设置一个回调函数,在run()执行之前被调用。


  • setprofile(func):设置一个回调函数,在run()执行完毕之后调用。


  • stack_size():返回创建新线程时使用的线程堆栈大小。


  • threading.TIMEOUT_MAX:堵塞线程时间最大值,超过这个值会栈溢出。


② 线程局部变量(Thread-Local Data)


问题引入:


在一个进程内所有的线程共享进程的全局变量,线程间共享数据很方便但是每个线程都可以随意修改全局变量,可能会引起线程安全问题。


解决方法:


对于这种线程私有数据,最简单的方法就是对变量加锁或使用局部变量,只有线程自身可以访问,其他线程无法访问。除此之外还可以使用threading模块为我们提供的ThreadLocal变量,它本身是一个全局变量,但是线程们却可以使用它来保存私有数据。


用法简介:


定义一个全局变量:data = thread.local(),然后就可以往里面存数据啦,比如data.num = xxx,但是有一点要注意:如果data里没有设置对应的属性,直接取会报AttributeError异常,使用时可以捕获这个异常或先调用hasattr(对象,属性)判断对象中是否有该属性!使用代码示例如下:


import threading
import random
data = threading.local()
def show(d):
    try:
        num = d.num
    except AttributeError:
        print("线程 %s 还未设置该属性!" % threading.current_thread().getName())
    else:
        print("线程 %s 中该属性的值为 = %s" % (threading.current_thread().getName(), num))
def thread_call(d):
    show(d)
    d.num = random.randint(1, 100)
    show(d)
if __name__ == '__main__':
    show(data)
    data.num = 666
    show(data)
    for i in range(2):
        t = threading.Thread(target=thread_call, args=(data,), name="Thread " + str(i))
        t.start()


运行结果如下


线程 MainThread 还未设置该属性!
线程 MainThread 中该属性的值为 = 666
线程 Thread 0 还未设置该属性!
线程 Thread 0 中该属性的值为 = 80
线程 Thread 1 还未设置该属性!
线程 Thread 1 中该属性的值为 = 17


不同线程访问这个ThreadLocal变量,返回的都是不一样的值,原理:


threading.local()实例化一个全局对象,这个全局对象里有一个大字典,键值为两个弱引用对象{线程对象,字典对象},然后可以通过current_thread()获得当前的线程对象,然后根据这个对象可以拿到对应的字典对象,然后进行参数的读或者写。


③ 线程对象(threading.Thread)


创建新线程的两种方式:


  • 1.直接创建threading.Thread对象并把调用对象作为参数传入


  • 2.继承threading.Thread类重写run()方法


使用代码示例(验证单线程快还是多线程快):


import threading
import time
def catch_fish():
    pass
def one_thread():
    start_time = time.time()
    for i in range(1, 1001):
        catch_fish()
    end_time = time.time()
    print("单线程测试 耗时 === %s" % str(end_time - start_time))
def muti_thread():
    start_time = time.time()
    for i in range(1, 1001):
        threading.Thread(target=catch_fish()).start()
    end_time = time.time()
    print("多线程测试 耗时 === %s" % str(end_time - start_time))
if __name__ == '__main__':
    # 单线程
    threading.Thread(one_thread()).start()
    # 多线程
    muti_thread()


运行结果如下:


单线程测试 耗时 === 0.00011301040649414062
多线程测试 耗时 === 0.07665514945983887


从输出结果可以看到,多线程反而比单线程要慢,原因是前面介绍过的Python中的全局解释器锁(GIL), 使得任何时候仅有一个线程在执行。


Thread类构造函数


def __init__(self, group=None, target=None, name=None,
                 args=(), kwargs=None, *, daemon=None):


构造函数参数依次是:


  • group:线程组


  • target:要执行的函数


  • name:线程名字


  • args/kwargs:要传入的函数的参数


  • daemon:是否为守护线程


相关属性与函数:


  • start():启动线程,只能调用一次


  • run():线程执行的操作,可继承Thread重写,参数可从args和kwargs获取;


  • join([timeout]):堵塞调用线程,直到被调用线程运行结束或超时;如果
    没设置超时时间会一直堵塞到被调用线程结束。


  • name/getName():获得线程名;


  • setName():设置线程名;


  • ident:线程是已经启动,未启动会返回一个非零整数;


  • is_alive():判断是否在运行,启动后,终止前;


  • daemon/isDaemon():线程是否为守护线程;


  • setDaemon():设置线程为守护线程;


④ Lock(指令锁)与RLock(可重入锁)


在概念那里就讲了,多个进程并发的访问临界资源可能会引起线程同步安全问题,写个简单的例子,然后再引入同步锁。代码示例如下:


import threading
file_name = "test.txt"
# 定义一个写入文件的方法
def write_to_file(msg):
    try:
        with open(file_name, "a+", encoding="utf-8") as f:
            f.write(msg + "\n")
    except OSError as reason:
        print(str(reason))
class MyThread(threading.Thread):
    def __init__(self, msg):
        super().__init__()
        self.msg = msg
    def run(self):
        write_to_file(self.name + "~" + self.msg)
if __name__ == '__main__':
    for i in range(1, 21):
        t = MyThread(str(i)).start()


运行结果如下


# test.txt文件内容
Thread-1~1
Thread-5~5
Thread-3~3
Thread-2~2
Thread-4~4
Thread-6~6
Thread-7~7
Thread-8~8
Thread-10~10
Thread-9~9
Thread-11~11
Thread-13~13
Thread-12~12
Thread-14~14
Thread-15~15
Thread-16~16
Thread-17~17
Thread-19~19
Thread-20~20
Thread-18~18

发现结果并没有按照我们预想的1-20那样顺序打印,而是乱的,threading模块中提供了两个类来确保多线程共享资源的访问:「Lock」 和 「RLock」。


相关文章
|
2月前
|
调度 开发者 Python
深入浅出操作系统:进程与线程的奥秘
在数字世界的底层,操作系统扮演着不可或缺的角色。它如同一位高效的管家,协调和控制着计算机硬件与软件资源。本文将拨开迷雾,深入探索操作系统中两个核心概念——进程与线程。我们将从它们的诞生谈起,逐步剖析它们的本质、区别以及如何影响我们日常使用的应用程序性能。通过简单的比喻,我们将理解这些看似抽象的概念,并学会如何在编程实践中高效利用进程与线程。准备好跟随我一起,揭开操作系统的神秘面纱,让我们的代码运行得更加流畅吧!
|
18天前
|
消息中间件 调度
如何区分进程、线程和协程?看这篇就够了!
本课程主要探讨操作系统中的进程、线程和协程的区别。进程是资源分配的基本单位,具有独立性和隔离性;线程是CPU调度的基本单位,轻量且共享资源,适合并发执行;协程更轻量,由程序自身调度,适合I/O密集型任务。通过学习这些概念,可以更好地理解和应用它们,以实现最优的性能和资源利用。
52 11
|
17天前
|
Java Linux 调度
硬核揭秘:线程与进程的底层原理,面试高分必备!
嘿,大家好!我是小米,29岁的技术爱好者。今天来聊聊线程和进程的区别。进程是操作系统中运行的程序实例,有独立内存空间;线程是进程内的最小执行单元,共享内存。创建进程开销大但更安全,线程轻量高效但易引发数据竞争。面试时可强调:进程是资源分配单位,线程是CPU调度单位。根据不同场景选择合适的并发模型,如高并发用线程池。希望这篇文章能帮你更好地理解并回答面试中的相关问题,祝你早日拿下心仪的offer!
32 6
|
2月前
|
消息中间件 Unix Linux
【C语言】进程和线程详解
在现代操作系统中,进程和线程是实现并发执行的两种主要方式。理解它们的区别和各自的应用场景对于编写高效的并发程序至关重要。
73 6
|
2月前
|
调度 开发者
深入理解:进程与线程的本质差异
在操作系统和计算机编程领域,进程和线程是两个核心概念。它们在程序执行和资源管理中扮演着至关重要的角色。本文将深入探讨进程与线程的区别,并分析它们在现代软件开发中的应用和重要性。
72 5
|
2月前
|
算法 调度 开发者
深入理解操作系统:进程与线程的管理
在数字世界的复杂编织中,操作系统如同一位精明的指挥家,协调着每一个音符的奏响。本篇文章将带领读者穿越操作系统的幕后,探索进程与线程管理的奥秘。从进程的诞生到线程的舞蹈,我们将一起见证这场微观世界的华丽变奏。通过深入浅出的解释和生动的比喻,本文旨在揭示操作系统如何高效地处理多任务,确保系统的稳定性和效率。让我们一起跟随代码的步伐,走进操作系统的内心世界。
|
2月前
|
调度 开发者
核心概念解析:进程与线程的对比分析
在操作系统和计算机编程领域,进程和线程是两个基本而核心的概念。它们是程序执行和资源管理的基础,但它们之间存在显著的差异。本文将深入探讨进程与线程的区别,并分析它们在现代软件开发中的应用和重要性。
71 4
|
3月前
|
数据采集 存储 数据处理
Python中的多线程编程及其在数据处理中的应用
本文深入探讨了Python中多线程编程的概念、原理和实现方法,并详细介绍了其在数据处理领域的应用。通过对比单线程与多线程的性能差异,展示了多线程编程在提升程序运行效率方面的显著优势。文章还提供了实际案例,帮助读者更好地理解和掌握多线程编程技术。
|
3月前
|
并行计算 数据处理 调度
Python中的并发编程:探索多线程与多进程的奥秘####
本文深入探讨了Python中并发编程的两种主要方式——多线程与多进程,通过对比分析它们的工作原理、适用场景及性能差异,揭示了在不同应用需求下如何合理选择并发模型。文章首先简述了并发编程的基本概念,随后详细阐述了Python中多线程与多进程的实现机制,包括GIL(全局解释器锁)对多线程的影响以及多进程的独立内存空间特性。最后,通过实例演示了如何在Python项目中有效利用多线程和多进程提升程序性能。 ####
|
3月前
|
监控 JavaScript 前端开发
python中的线程和进程(一文带你了解)
欢迎来到瑞雨溪的博客,这里是一位热爱JavaScript和Vue的大一学生分享技术心得的地方。如果你从我的文章中有所收获,欢迎关注我,我将持续更新更多优质内容,你的支持是我前进的动力!🎉🎉🎉
41 0

热门文章

最新文章