广告
返回顶部
首页 > 资讯 > 后端开发 > Python >python 多进程和多线程使用详解
  • 841
分享到

python 多进程和多线程使用详解

2024-04-02 19:04:59 841人浏览 安东尼

Python 官方文档:入门教程 => 点击学习

摘要

目录进程和线程 python的多进程 进程池 多进程间的数据通信与共享 Python的多线程 多线程间的数据共享 使用queue队列通信-经典的生产者和消费者模型进程和线程 进程是

进程和线程

进程是系统进行资源分配的最小单位,线程是系统进行调度执行的最小单位;

一个应用程序至少包含一个进程,一个进程至少包含一个线程;

每个进程在执行过程中拥有独立的内存空间,而一个进程中的线程之间是共享该进程的内存空间的;

  • 计算机的核心是CPU,它承担了所有的计算任务。它就像一座工厂,时刻在运行。
  • 假定工厂的电力有限,一次只能供给一个车间使用。也就是说,一个车间开工的时候,其他车间都必须停工。背后的含义就是,单个CPU一次只能运行一个任务。编者注: 多核的CPU就像有了多个发电厂,使多工厂(多进程)实现可能。
  • 进程就好比工厂的车间,它代表CPU所能处理的单个任务。任一时刻,CPU总是运行一个进程,其他进程处于非运行状态。
  • 一个车间里,可以有很多工人。他们协同完成一个任务。
  • 线程就好比车间里的工人。一个进程可以包括多个线程。
  • 车间的空间是工人们共享的,比如许多房间是每个工人都可以进出的。这象征一个进程的内存空间是共享的,每个线程都可以使用这些共享内存。
  • 可是,每间房间的大小不同,有些房间最多只能容纳一个人,比如厕所。里面有人的时候,其他人就不能进去了。这代表一个线程使用某些共享内存时,其他线程必须等它结束,才能使用这一块内存。
  • 一个防止他人进入的简单方法,就是门口加一把。先到的人锁上门,后到的人看到上锁,就在门口排队,等锁打开再进去。这就叫"互斥锁"(Mutual exclusion,缩写 Mutex),防止多个线程同时读写某一块内存区域。
  • 还有些房间,可以同时容纳n个人,比如厨房。也就是说,如果人数大于n,多出来的人只能在外面等着。这好比某些内存区域,只能供给固定数目的线程使用。
  • 这时的解决方法,就是在门口挂n把钥匙。进去的人就取一把钥匙,出来时再把钥匙挂回原处。后到的人发现钥匙架空了,就知道必须在门口排队等着了。这种做法叫做"信号量"(Semaphore),用来保证多个线程不会互相冲突。
  • 不难看出,mutex是semaphore的一种特殊情况(n=1时)。也就是说,完全可以用后者替代前者。但是,因为mutex较为简单,且效率高,所以在必须保证资源独占的情况下,还是采用这种设计。

Python的多进程

Python的多进程依赖于multiprocess模块;使用多进程可以利用多个CPU进行并行计算;

实例:


from multiprocessing import Process
import os
import time
 
def long_time_task(i):
    print('子进程: {} - 任务{}'.fORMat(os.getpid(), i))
    time.sleep(2)
    print("结果: {}".format(8 ** 20))
 
if __name__=='__main__':
    print('当前母进程: {}'.format(os.getpid()))
    start = time.time()
    p1 = Process(target=long_time_task, args=(1,))
    p2 = Process(target=long_time_task, args=(2,))
    print('等待所有子进程完成。')
    p1.start()
    p2.start()
    p1.join()
    p2.join()
    end = time.time()
    print("总共用时{}秒".format((end - start)))

新创建进程和进程间切换是需要消耗资源的,所以应该控制进程数量;

同时可运行的进程数量收到CPU核数限制;

进程池

使用进程池pool创建进程:

使用进程池可以避免手工进行进程的创建的麻烦,默认数量是CPU核数;

Pool类可以提供指定数量的进程供用户使用,当有新的请求被提交到Pool中的时候,如果进程池还没有满,就会创建一个新的进程来执行请求;如果池已经满了,请求就会等待,等到有空闲进程可以使用时,才会执行请求;

几个方法:

1.apply_async

作用是向进程池提交需要执行的函数和参数,各个进程采用非阻塞的异步方式调用,每个进程只管自己运行,是默认方式;

2.map

会阻塞进程直到返回结果;

3.map_sunc

非阻塞进程;

4.close

关闭进程池,不再接受任务;

5.terminate

结束进程;

6.join

主进程阻塞,直到子进程执行结束;

实例:


from multiprocessing import Pool, cpu_count
import os
import time
 
def long_time_task(i):
    print('子进程: {} - 任务{}'.format(os.getpid(), i))
    time.sleep(2)
    print("结果: {}".format(8 ** 20))
 
if __name__=='__main__':
    print("CPU内核数:{}".format(cpu_count()))
    print('当前母进程: {}'.format(os.getpid()))
    start = time.time()
    p = Pool(4)
    for i in range(5):
        p.apply_async(long_time_task, args=(i,))
    print('等待所有子进程完成。')
    p.close()
    p.join()
    end = time.time()
    print("总共用时{}秒".format((end - start)))

在join之前,必须使用close或者terminate,让进程池不再接受任务;

多进程间的数据通信与共享

通常,进程之间是相互独立的,每个进程都有独立的内存。通过共享内存(nmap模块),进程之间可以共享对象,使多个进程可以访问同一个变量(地址相同,变量名可能不同)。多进程共享资源必然会导致进程间相互竞争,所以应该尽最大可能防止使用共享状态。还有一种方式就是使用队列queue来实现不同进程间的通信或数据共享,这一点和多线程编程类似。

下例这段代码中中创建了2个独立进程,一个负责写(pw), 一个负责读(pr), 实现了共享一个队列queue。


from multiprocessing import Process, Queue
import os, time, random
 
# 写数据进程执行的代码:
def write(q):
    print('Process to write: {}'.format(os.getpid()))
    for value in ['A', 'B', 'C']:
        print('Put %s to queue...' % value)
        q.put(value)
        time.sleep(random.random())
 
# 读数据进程执行的代码:
def read(q):
    print('Process to read:{}'.format(os.getpid()))
    while True:
        value = q.get(True)
        print('Get %s from queue.' % value)
 
if __name__=='__main__':
    # 父进程创建Queue,并传给各个子进程:
    q = Queue()
    pw = Process(target=write, args=(q,))
    pr = Process(target=read, args=(q,))
    # 启动子进程pw,写入:
    pw.start()
    # 启动子进程pr,读取:
    pr.start()
    # 等待pw结束:
    pw.join()
    # pr进程里是死循环,无法等待其结束,只能强行终止:
    pr.terminate()

Python的多线程

python 3中的多进程编程主要依靠threading模块。创建新线程与创建新进程的方法非常类似。threading.Thread方法可以接收两个参数, 第一个是target,一般指向函数名,第二个时args,需要向函数传递的参数。对于创建的新线程,调用start()方法即可让其开始。我们还可以使用current_thread().name打印出当前线程的名字。 


import threading
import time
 
def long_time_task(i):
    print('当前子线程: {} 任务{}'.format(threading.current_thread().name, i))
    time.sleep(2)
    print("结果: {}".format(8 ** 20))
 
if __name__=='__main__':
    start = time.time()
    print('这是主线程:{}'.format(threading.current_thread().name))
    thread_list = []
    for i in range(1, 3):
        t = threading.Thread(target=long_time_task, args=(i, ))
        thread_list.append(t)
    for t in thread_list:
        t.start()
    for t in thread_list:
        t.join()
    end = time.time()
    print("总共用时{}秒".format((end - start)))

多线程间的数据共享

一个进程所含的不同线程间共享内存,这就意味着任何一个变量都可以被任何一个线程修改,因此线程之间共享数据最大的危险在于多个线程同时改一个变量,把内容给改乱了。如果不同线程间有共享的变量,其中一个方法就是在修改前给其上一把锁lock,确保一次只有一个线程能修改它。threading.lock()方法可以轻易实现对一个共享变量的锁定,修改完后release供其它线程使用。


import threading
 
class Account:
    def __init__(self):
        self.balance = 0
 
    def add(self, lock):
        # 获得锁
        lock.acquire()
        for i in range(0, 100000):
            self.balance += 1
        # 释放锁
        lock.release()
 
    def delete(self, lock):
        # 获得锁
        lock.acquire()
        for i in range(0, 100000):
            self.balance -= 1
            # 释放锁
        lock.release()
 
if __name__ == "__main__":
    account = Account()
    lock = threading.Lock()
    # 创建线程
   thread_add = threading.Thread(target=account.add, args=(lock,), name='Add')
    thread_delete = threading.Thread(target=account.delete, args=(lock,), name='Delete')
 
    # 启动线程
   thread_add.start()
    thread_delete.start()
 
    # 等待线程结束
   thread_add.join()
    thread_delete.join()
 
    print('The final balance is: {}'.format(account.balance))

使用queue队列通信-经典的生产者和消费者模型


from queue import Queue
import random, threading, time
 
# 生产者类
class Producer(threading.Thread):
    def __init__(self, name, queue):
        threading.Thread.__init__(self, name=name)
        self.queue = queue
 
    def run(self):
        for i in range(1, 5):
            print("{} is producing {} to the queue!".format(self.getName(), i))
            self.queue.put(i)
            time.sleep(random.randrange(10) / 5)
        print("%s finished!" % self.getName())
 
# 消费者类
class Consumer(threading.Thread):
    def __init__(self, name, queue):
        threading.Thread.__init__(self, name=name)
        self.queue = queue
 
    def run(self):
        for i in range(1, 5):
            val = self.queue.get()
            print("{} is consuming {} in the queue.".format(self.getName(), val))
            time.sleep(random.randrange(10))
        print("%s finished!" % self.getName())
 
def main():
    queue = Queue()
    producer = Producer('Producer', queue)
    consumer = Consumer('Consumer', queue)
 
    producer.start()
    consumer.start()
 
    producer.join()
    consumer.join()
    print('All threads finished!')
 
if __name__ == '__main__':
    main()
  • 对CPU密集型代码(比如循环计算) - 多进程效率更高
  • 对IO密集型代码(比如文件操作,网络爬虫) - 多线程效率更高。

对于IO密集型操作,大部分消耗时间其实是等待时间,在等待时间中CPU是不需要工作的,那你在此期间提供双CPU资源也是利用不上的,相反对于CPU密集型代码,2个CPU干活肯定比一个CPU快很多。那么为什么多线程会对IO密集型代码有用呢?这时因为python碰到等待会释放GIL供新的线程使用,实现了线程间的切换。

以上就是python 多进程和多线程使用详解的详细内容,更多关于python 多进程和多线程的资料请关注编程网其它相关文章!

--结束END--

本文标题: python 多进程和多线程使用详解

本文链接: https://www.lsjlt.com/news/122567.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • python 多进程和多线程使用详解
    目录进程和线程 Python的多进程 进程池 多进程间的数据通信与共享 Python的多线程 多线程间的数据共享 使用queue队列通信-经典的生产者和消费者模型进程和线程 进程是...
    99+
    2022-11-12
  • Python多线程详解
    现代计算机CPU物理核心普遍比较多,我们在编写程序时经常会用到多线程技术来提高程序运行的效率。作为python萌新,我在掌握基本语法后就很想摆弄一下python的多线程,使用起来确实很有pytho...
    99+
    2023-09-08
    python
  • 详解Python多线程
    本文实例为大家解析了Python多线程,供大家参考,具体内容如下 1、多线程的理解 多进程和多线程都可以执行多个任务,线程是进程的一部分。线程的特点是线程之间可以共享内存和变量,资源消耗少(不过在Unix环...
    99+
    2022-06-04
    多线程 详解 Python
  • 分析详解python多线程与多进程区别
    目录1 基础知识1.1 线程1.2 进程1.3 两者的区别2 Python 多进程2.1 创建多进程方法1:直接使用Process方法2:继承Process来自定义进程类,重写run...
    99+
    2022-11-12
  • python socket多线程和多进程
    在socket中,如果直接创建的话,是只能接受一个用户的请求需要实现socketserver中的handle方法,可以实现多进程并发访问 SocketServer内部使用 IO多路复用 以及 “多线程” 和 “多进程” ,从而实现并发处理...
    99+
    2023-01-31
    多线程 进程 python
  • python多线程和多进程(二)
    ---恢复内容开始--- 一、多进程   1、multiprocessing模块用来开启子进程,并在子进程中执行我们定制的任务(比如函数),该模块与多线程模块threading的编程接口类似。 import time from mult...
    99+
    2023-01-30
    多线程 进程 python
  • python并发编程之多进程、多线程、异步和协程详解
    最近学习python并发,于是对多进程、多线程、异步和协程做了个总结。 一、多线程 多线程就是允许一个进程内存在多个控制权,以便让多个函数同时处于激活状态,从而让多个函数的操作同时运行。即使是单CPU的计...
    99+
    2022-06-04
    之多 多线程 详解
  • python多进程和多线程介绍
    目录一、什么是进程和线程 二、多进程和多线程 三、python中的多进程和多线程1、多进程2、多线程一、什么是进程和线程  进程是分配资源的最小单位,线...
    99+
    2022-11-10
  • python中多进程和多线程的使用方法
    这篇文章主要介绍了python中多进程和多线程的使用方法,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。进程和线程进程是系统进行资源分配的最小单位,线程是系统进行调度执行的最小...
    99+
    2023-06-14
  • Python线程之多线程展示详解
    目录什么多线程?获取活跃线程相关数据总结什么多线程? 多线程,就是多个独立的运行单位,同时执行同样的事情。 想想一下,文章发布后同时被很多读者阅读,这些读者在做的事情‘阅读'就是一...
    99+
    2022-11-12
  • python多线程超详细详解
    python中的多线程是一个非常重要的知识点,今天为大家对多线程进行详细的说明,代码中的注释有多线程的知识点还有测试用的实例。 import threading from thr...
    99+
    2022-11-12
  • python多进程和多线程的实际用法
    这篇文章主要讲解了“python多进程和多线程的实际用法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“python多进程和多线程的实际用法”吧!  写在前面  总所周知,unix/linux...
    99+
    2023-06-02
  • python多线程方法详解
    处理多个数据和多文件时,使用for循环的速度非常慢,此时需要用多线程来加速运行进度,常用的模块为multiprocess和joblib,下面对两种包我常用的方法进行说明。 1、模块安...
    99+
    2022-11-12
  • Python 多线程实例详解
    Python 多线程实例详解 多线程通常是新开一个后台线程去处理比较耗时的操作,Python做后台线程处理也是很简单的,今天从官方文档中找到了一个Demo. 实例代码: import threading...
    99+
    2022-06-04
    多线程 详解 实例
  • 详解Python中的多线程
    目录什么是多线程:threading模块守护线程与join方法线程锁(互斥锁Mutex)GIL VS LockRLock(递归锁)Semaphore(信号量)Event(事件)生产者...
    99+
    2022-11-11
  • Python多线程和多进程在什么场景中使用
    这篇文章主要介绍“Python多线程和多进程在什么场景中使用”,在日常操作中,相信很多人在Python多线程和多进程在什么场景中使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Python多线程和多进程在什...
    99+
    2023-06-16
  • python之多线程与多进程
    1. 多进程与多线程 (1)背景:为何需要多进程或者多线程:在同一时间里,同一个计算机系统中如果允许两个或者两个以上的进程处于运行状态,这便是多任务。多任务会带来的好处例如用户边听歌、边上网、边打印,而这些任务之间丝毫不会互相干扰。使用多...
    99+
    2023-01-31
    之多 线程 进程
  • Python学习记录-多进程和多线程
    [TOC] 1. 进程和线程 进程 狭义定义:进程是正在运行的程序的实例(an instance of a computer program that is being executed)。广义定义:进程是一个具有一定独立功能的程序关于某...
    99+
    2023-01-31
    多线程 进程 Python
  • Python多线程编程入门详解
    目录一、任务、进程和线程任务进程线程进程和线程的关系二、Python既支持多进程,又支持多线程Python实现多进程Process进程类的说明Python实现多线程线程类Thread...
    99+
    2022-11-12
  • Python多线程的使用详情
    目录一,实用方法二、补充:Python多线程共享变量资源竞争问题一,实用方法 1.线程之间执行是无序的,cpu调度哪个线程就执行哪个线程;2.主线程等待所有子线程结束后再结束,设置守...
    99+
    2022-11-10
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作