MultiProcess-MultiThread

听到一些关于python多进程与多线的例子,感觉比较经典,把一些例子分享一下.

内容如下:

    Process、Thread、GIL、Process fork、Multiprocessing、Queue、ProcessPool、Multiprocess-Multithread comparison


(1) Process : 程序的一次执行(程序编写完毕后代码装载入内存,系统分配资源运行)。每个进程有自己的内存空间、数据栈等,只能使用进 程间通讯,而不能直接共享信息 


(2) Thread线程:所有线程运行在同一个进程中,共享相同的运行环境。 每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口; 线程的运行可以被抢占(中断),或暂时被挂起 (睡眠),让其他线程运行(让步);一个进程中的各个线程间共享同一片数据空间 


(3) 全局解释器锁GIL 

    GIL全称全局解释器锁Global Interpreter Lock,GIL并不是Python的特性,它是在实现Python解析器(CPython) 所引入的一个概念。 

    GIL是一把全局排他锁,同一时刻只有一个线程在运行。 毫无疑问全局锁的存在会对多线程的效率有不小影响。甚至就几乎等于Python是个单线程的程序。 

    multiprocessing库的出现很大程度上是为了弥补thread库因为 GIL而低效的缺陷。它完整的复制了一套thread所提供的接口方便迁移。唯一的不同就是它使用了多进程而不是多线程。每个进程有自己的独立的GIL,因此也不会出现进程之间的GIL争抢。 


多线程处理的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from threading import Thread
import time
def my_counter():
    = 0
    for in range(100000000):
        =i+1
    return True
def main():
    thread_array = {}
    start_time = time.time()
    for tid in range(2):
        = Thread(target=my_counter())
        t.start()
        t.join()
        #以单线程、阻塞的方式顺序运行两次my_counter函数
    end_time = time.time()
    print("Total time:{}").format(end_time - start_time)
     
if __name__=="__main__":
    main()

执行结果如下:

Total time:12.7875118256


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from threading import Thread
import time
def my_counter():
    = 0
    for in range(100000000):
        = i+1
    return True
def main():
    thread_array = {}
    start_time = time.time()
    for tid in range(2):
        = Thread(target=my_counter())
        t.start()
        thread_array[tid] = t
    for in range(2):
        thread_array[i].join()
        #以多进程、并发的方式运行两次my_counter函数
    end_time = time.time()
    print("Total time:{}").format(end_time - start_time)
     
if __name__=="__main__":
    main()

执行结果如下:

Total time:15.8216409683


上述两个例子的结果发现:单线程运行两次函数的时间   要比   两个线程同时运行函数的时间短(仅限于本例)。


(4) fork操作: 

调用一次,返回两次。因为操作系统自动把当前进程(称为父 进程)复制了一份(称为子进程),然后分别在父进程和子进 程内返回。子进程永远返回0,而父进程返回子进程的ID。子 进程只需要调用getppid()就可以拿到父进程的ID

例:

1
2
3
4
5
6
7
import os
print 'Process (%s) start ...' % os.getpid()
pid=os.fork()
if pid==0:
    print 'I am child process (%s) and my parent is (%s)' % (os.getpid(),os.getppid())
else:
    print 'I (%s) just created a child process (%s).' % (os.getpid(),pid)

执行结果如下:

Process (16480) start ...

I (16480) just created a child process (16481).

I am child process (16481) and my parent is (16480)


(5) multiprocessing是跨平台版本的多进程模块,它提供了一个Process类来代表一个进程对象,下面是示例代码: 

1
2
3
4
5
6
7
8
9
10
11
from multiprocessing import Process
import time
def f(n):
    time.sleep(1)
    print n*n
     
if __name__=="__main__":
    for in range(10):
        p=Process(target=f,args=[i,])
        p.start()
        #使用多进程并发的方式执行函数f

这个程序如果用单进程写则需要执行10秒以上的时间而用多进程则启动10个进程并行执行,只需要用1秒多的时间。多进程时,每个进程各自有各自的GIL。而同一进程中的多线程受到GIL的影响,效率返而会下降。


(6) Queue是多进程安全的队列,可以使用Queue实现多进程之间的数据传递 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from multiprocessing import Process,Queue
import time
def write(q):
    for in ['A','B','C','D','E']:
        print ('Put %s to queue' % i)
        q.put(i)
        time.sleep(0.5)
                
def read(q):
    while True:
        = q.get(True)
        print('get %s from queue' %v)
         
if __name__ == '__main__':
    = Queue()
    pw = Process(target=write,args=(q,))
    pr = Process(target=read,args=(q,))
    pw.start()
    pr.start()
    pr.join()
    pr.terminate()

输出结果:

Put A to queue

get A from queue

Put B to queue

get B from queue

Put C to queue

get C from queue

Put D to queue

get D from queue

Put E to queue

get E from queue


(7) 进程池pool 用于批量创建子进程,可以灵活控制子进程的数量 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from multiprocessing import Pool
import time
def f(x):
    print x*x
    time.sleep(2)
    return x*x
if __name__ == '__main__':
    pool = Pool(processes=5)
    res_list = []
    for in range(10):        
        res = pool.apply_async(f,[i,])
        ''' 以异步并行的方式启动进程处理函数f,如果要同步等待的方式,可以在每次进程启动之后调用res.get()方法,也可以使用Pool.apply'''
        print('-------:',i)
        res_list.append(res)
    pool.close()
    pool.join()
    for in res_list:
        print 'result',(r.get(timeout=5))

输出结果如下:

('-------:', 0)

('-------:', 1)

('-------:', 2)

('-------:', 3)

('-------:', 4)

('0-------:', 5)

('-------:', 6)

('-------:', 7)

1

('-------:', 8)

('-------:', 9)

4

16

9

25

36

49

64

81

result 0

result 1

result 4

result 9

result 16

result 25

result 36

result 49

result 64

result 81

如果使用同步方式,处理函数时 必须等待 前一个处理的结束,所以如果将该程序换为同步方式,输出结果则是顺序的。


(8) 多进程与多线程的对比

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from multiprocessing import Process
import threading
import time
lock = threading.Lock()
def run(info_list,n):
    lock.acquire()
    info_list.append(n)
    lock.release()
    print('%s' % info_list)
if __name__ == '__main__':
    info = []
    for in range(10):
        = Process(target=run,args=[info,i])
        p.start()
        p.join()
    time.sleep(1)
    print('-----------------threading--------------')
    for in range(10):
        = threading.Thread(target=run,args=[info,i])
        p.start()
        p.join()

输出结果为:

[0]

[1]

[2]

[3]

[4]

[5]

[6]

[7]

[8]

[9]

-----------------threading--------------

[0]

[0, 1]

[0, 1, 2]

[0, 1, 2, 3]

[0, 1, 2, 3, 4]

[0, 1, 2, 3, 4, 5]

[0, 1, 2, 3, 4, 5, 6]

[0, 1, 2, 3, 4, 5, 6, 7]

[0, 1, 2, 3, 4, 5, 6, 7, 8]

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]


多进程间数据不能直接共享,每次处理函数run的结果都不能继承。而多线程间数据可以共享,但受到GIL的影响,run函数中在将数据追加到列表时,使用lock锁,追回完毕再释放lock,这样避免冲突。










本文转自 meteor_hy 51CTO博客,原文链接:http://blog.51cto.com/caiyuanji/1966279,如需转载请自行联系原作者

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/286135.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【MATLAB统计分析与应用100例】案例005:matlab调用medfilt1函数对加噪正弦波信号进行平滑处理

平滑效果预览: 文章目录 1. 产生加噪正弦波信号,绘制加噪波形图2. 调用medfilt1对加噪正弦波信号y进行中值滤波,并绘制波形图1. 产生加噪正弦波信号,绘制加噪波形图 t = linspace(0,2*pi,500); % 产生一个从0到2

十、为影院添加影片及座位安排《仿淘票票系统前后端完全制作(除支付外)》

一、选中添加功能完成 首先打开在线编辑器进入我们的项目:https://editor.ivx.cn/ 在上一节咱们已经完成了对应的准备工作,在这一节中,咱们只需要对其进行调用即可,调用前还需要处理这些数据: 首先选中时&#xff0…

遍历文件夹还原数据库SQL语句

/***** 遍历文件夹进行数据库还原 *******/---需要开启xp_cmdshell 如已经开启 可以略过 /***** Step 1 开启 xp_cmdshell Use Master GO EXEC master.dbo.sp_configure show advanced options, 1 RECONFIGURE WITH OVERRIDE GO EXEC master.dbo.sp_configure xp_cmdshell, 1…

聊聊 C# 和 C++ 中的 泛型模板 底层玩法

最近在看 C 的方法和类模板,我就在想 C# 中也是有这个概念的,不过叫法不一样,人家叫模板,我们叫泛型,哈哈,有点意思,这一篇我们来聊聊它们底层是怎么玩的?一:C 中的模板玩…

ceph集群报 Monitor clock skew detected 错误问题排查,解决

ceph集群报 Monitor clock skew detected 错误问题排查,解决 告警信息如下: [rootceph-100-80 ceph]# ceph -w cluster ddc1b10b-6d1a-4ef9-8a01-d561512f3c1d health HEALTH_WARN clock skew detected on mon.ceph-100-81,…

Java实现画八卦

八卦是由多个圆叠加而成,如果我们让每个圆都有自己的颜色,那么具体结构便一目了然,如下图所示: 显然只要令对应的圆颜色相同,就能达到我们预期的效果。 用Java就能轻松画出来: import java.awt.BasicStroke…

C语言试题四十五之把第1到第p个字符,平移到字符串的最后,把第p+1到最后的字符移到字符串的前部。

📃个人主页:个人主页 🔥系列专栏:C语言试题200例目录 💬推荐一款刷算法、笔试、面经、拿大公司offer神器 👉 点击跳转进入网站 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 请编写一个…

【MATLAB统计分析与应用100例】案例006:matlab数据的标准化变换

文章目录 1. 调用rand函数产生一个10行,4列的随机矩阵,每列服从不同的均匀分布2. 调用zscore函数对x进行标准化变换(按列标准化),返回变换后矩阵xz,以及矩阵x各列的均值构成的向量mu,各列的标准差构成的向量sigma3. 变换结果1. 调用rand函数产生一个10行,4列的随机矩阵…

十一、为影院添加影片制作准备服务《仿淘票票系统前后端完全制作(除支付外)》

一、为影院添加影片的逻辑和思考 首先打开在线编辑器进入我们的项目:https://editor.ivx.cn/ 进入之后找到上一节中制作的页面,咱们设置点击编辑按钮后进入的页面为影院添加影片页: 接着咱们查看影院添加影片页: 在该页中&…

Linux 内核中断内幕【转】

转自:http://www.ibm.com/developerworks/cn/linux/l-cn-linuxkernelint/ 本文对中断系统进行了全面的分析与探讨,主要包括中断控制器、中断分类、中断亲和力、中断线程化与 SMP 中的中断迁徙等。首先对中断工作原理进行了简要分析,接着详细探讨了中断亲…

SQL Server表分区

SQL Server表分区 什么是表分区 一般情况下,我们建立数据库表时,表数据都存放在一个文件里。 但是如果是分区表的话,表数据就会按照你指定的规则分放到不同的文件里,把一个大的数据文件拆分为多个小文件,还可以把这…

apt 根据注解,编译时生成代码

apt: Retention后面的值,设置的为CLASS,说明就是编译时动态处理的。一般这类注解会在编译的时候,根据注解标识,动态生成一些类或者生成一些xml都可以,在运行时期,这类注解是没有的~~会依靠动态生…

Web.config配置文件详解(新手必看)

花了点时间整理了一下ASP.NET Web.config配置文件的基本使用方法。很适合新手参看&#xff0c;由于Web.config在使用很灵活&#xff0c;可以自定义一些节点。所以这里只介绍一些比较常用的节点。 <?xml version"1.0"?> <!--注意: 除了手动编辑此文件以外&…

Hello Playwright:(6)与元素交互

在上一节我们已经了解到如何定位到元素&#xff0c;那么接下来就可以与元素进行交互了。下面的例子都是以百度首页作为测试页面输入文本FillAsync方法用于模拟用户选中元素并输入文本&#xff0c;这会触发元素的 input 事件。该方法只适合<input>、<textarea>等可输…

C语言试题四十六之将m行n列的二维数组中的字符数据,按列的顺序依次放到一个字符串中。

📃个人主页:个人主页 🔥系列专栏:C语言试题200例目录 💬推荐一款刷算法、笔试、面经、拿大公司offer神器 👉 点击跳转进入网站 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 请编写一个…

【MATLAB统计分析与应用100例】案例007:matlab数据的极差归一化变换

文章目录 1. 调用rand函数产生一个10行,4列的随机矩阵,每列服从不同的均匀分布2. 调用rscore函数对x按列进行极差规格化变换, 返回变换后矩阵R,以及矩阵x各列的最小值构成的向量xmin,各列的极差构成的向量xrange1. 调用rand函数产生一个10行,4列的随机矩阵,每列服从不同…

十二、动态座位响应及用户订票《仿淘票票系统前后端完全制作(除支付外)》

一、动态座位设置及发布 首先打开在线编辑器进入我们的项目&#xff1a;https://editor.ivx.cn/ 上一节中已经完成了座位设置的准备&#xff0c;这一节咱们将完成座位设置及发布的功能。 咱们首先给有座位设置事件&#xff1a; 有座位的事件设置当点击后更改当前的内容为0即…

跨服务器 快速 导入数据表记录 Insert into SELECT

Use DataBaseName/*开启Ad Hoc Distributed Queries组件exec sp_configure show advanced options,1 reconfigure exec sp_configure Ad Hoc Distributed Queries,1 reconfigure*/Insert into tableName (col1&#xff0c;col2&#xff0c;col3&#xff0c;……) --字段不能含有…

C# 查询大型数据集

LINQ 语法非常好&#xff0c;但其作用是什么&#xff1f;我们只要查看源数组&#xff0c;就可以看出需要的结果&#xff0c;为什么要查询这种一眼就能看出结果的数据源呢&#xff1f;有时查询的结果不那么明显&#xff0c;在下面的示例中&#xff0c;就创建了一个非常大的数字数…

C语言试题四十七之程序定义了N×M的二维数组,并在主函数中自动赋值。请编写函数function(int a[N][M], int m),该函数的功能是:将数组右上半三角元素中的值乘以m。

📃个人主页:个人主页 🔥系列专栏:C语言试题200例目录 💬推荐一款刷算法、笔试、面经、拿大公司offer神器 👉 点击跳转进入网站 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 程序定义了…