1. 首页
  2. IT资讯

说说python多进程,多线程

进程的引入:为了提高计算机系统的效率和增强计算机系统内各种硬件的并行操作能力,操作系统要求程序结构适应并发处理的需要,即时计算机系统中能同时存在两个以上的正在执行的的程序,顺序的程序的结构并不具备并发处理的能力,因此为了描述操作系统的并发性,就引入了进程这个概念。
进程是一个能独立运行的单位,能与其他程序并行的活动。从结构上说,每个进程都由一个程序段(数据)和一个进程控制块PCB组成。
单CPU情况下,多个进程会通过时间片轮转的方式轮流去占用CPU,实现并发,要实现并行的话得需要多CPU。
多进程轮流占用CPU时,需要做进程切换,进程1切换到进程2运行时,系统需要保留进程1运行时的所需的信息。

python 进程是通过multiprossing这个库来创建的。
1.启动方式有三种:
spawn :父进程启动一个新的Python解释器进程。子进程只会继承那些运行进程对象的 run() 方法所需的资源。特别是父进程中非必须的文件描述符和句柄不会被继承。相对于使用 fork 或者 forkserver,使用这个方法启动进程相当慢。
fork:父进程使用 os.fork() 来产生 Python 解释器分叉。子进程在开始时实际上与父进程相同。父进程的所有资源都由子进程继承。请注意,安全分叉多线程进程是棘手的。

只存在于Unix。Unix中的默认值。
forkserver:程序启动并选择 forkserver 启动方法时,将启动服务器进程。从那时起,每当需要一个新进程时,父进程就会连接到服务器并请求它分叉一个新进程。分叉服务器进程是单线程的,因此使用 os.fork() 是安全的。没有不必要的资源被继承。
可在Unix平台上使用,支持通过Unix管道传递文件描述符。

2.multiprossing支持的进程之间的通信方式有两种
队列:
使用Queue类,是一个类似queue.Queue的克隆

from multiprocessing import Process,Queue

def func(q):
    q.put(["python","Process"])
if __name__ == '__main__':
    q = Queue()
    p = Process(func,args=(q,)
    p.start()
    print(q.get()) # prints '["python","Process"]'
    p.join()

队列是线程和进程安全的
管道:
Pipe()函数返回一个由管道连接的连接对象,默认情况下是双工的

from multiprocessing import Process,Pipe

def func(conn):
    conn.send(["python","Process"])
    conn.close()
    
if __name__ == '__main__':
    parent_conn,child_conn = Pipe()
    p = Process(func,args=(child_conn,)
    p.start()
    print(parent_conn.recv()) # prints '["python","Process"]'
    p.join()

返回的两个连接对象Pipe()表示管道的两端。每个连接对象都有send()和revc()方法。请注意:如果两个进程或者线程同时尝试写入或读取管道同一端,则管道中的数据可能会损坏。当然如果是不同的进程同时使用管道的不同端的情况下不存在损坏的风险。

孤儿进程:多进程环境下,父进程先退出,而它的子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所回收。
僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中
清除僵尸进程的方式:
1.结束父进程,父进程结束子进程也就结束了,但是这个比较暴力,因为我们还是需要父进程继续运行的
2.通过wait调用来读取子进程退出状态。比如通过multiprocess.Process产生的进程可以通过子进程的join()方法来wait,也可以父进程中处理SIGCHLE信号,在处理程序中调用wai系统调用或者直接设置为SIG_IGN来清除僵尸进程。
3.就是把子进程变成孤儿进程

线程
线程的引入是因为多进程进行进程切换时开销较大。
线程是比进程更小的能独立运行的基本单位,试图通过线程来提高系统内程序并发执行效率。
由于进程是一个资源拥有者,因此在创建,撤销,切换这些动作中,系统必须付出较大的时间和空间开销。所以在系统中不宜设置过多的进程。这也就限制了并发程度的进一步提高。
人们就把进程作为资源分配单位和调度单位这两个属性分开处理,即进程还是作为资源分配的基本单位,但是不作为调度的基本单位(很少调度或者切换),把调度执行与切换的责任交给线程。这样线程的概念就形成了。
线程是一个轻量级进程,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点在运行中必不可少的资源,但它可与同属一个进程的其他线程共享进程所拥有的全部资源。

python中,通过threading库来产生线程

from threading import Thread

def func():
    print("-----")
   
if __name__ == '__main__':
    t = Thread(func)
    t.start()

本文来自投稿,不代表程序员编程网立场,如若转载,请注明出处:http://www.cxybcw.com/200430.html

联系我们

13687733322

在线咨询:点击这里给我发消息

邮件:1877088071@qq.com

工作时间:周一至周五,9:30-18:30,节假日休息

QR code