python 多进程 多线程 程序

这个纯粹为了增加理解,将很多比较好的资料进行归纳总结。

1、理论汇总

  • 并发和并行


    image.png
  • 多进程和多线程

  • 同步和异步
    同步:所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不会返回。

    异步:异步的概念和同步相对,当一个异步功能调用发出后,调用者不能立即
    得到结果。
    简单来说,同步就是必须一件一件事做,等前一件做完了才能做下一件事。
    同步和异步的区别:请求发出后,是否需要等待结果,才能继续执行其他操作。
    假设说有个函数func(param),里面会有若干个模块,最后返回一个结果,同步就是说等这个函数调用结束返回值之后才会往下继续。意思就是说,这个调用里,这几个模块会紧挨着顺序进行。
    而在异步中,这几个模块可能不是紧挨着的。
    举个例子如下

  • 什么是进程挂起
    参加下面阻塞时候的情况。
  • 什么是阻塞和非阻塞

阻塞和非阻塞这两个概念与程序(线程)等待消息通知(无所谓同步或者异步)时的状态有关。也就是说阻塞与非阻塞主要是程序(线程)等待消息通知时的状态角度来说的。

阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态.

阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。

非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。

  • 关于异步、同步、阻塞和非阻塞的区别
    同步/异步关注的是消息通知的机制,而阻塞/非阻塞关注的是程序(线程)等待消息通知时的状态。

以小明下载文件打个比方,从这两个关注点来再次说明这两组概念,希望能够更好的促进大家的理解。

同步阻塞:小明一直盯着下载进度条,到 100% 的时候就完成。

同步体现在:等待下载完成通知;

阻塞体现在:等待下载完成通知过程中,不能做其他任务处理;

同步非阻塞:小明提交下载任务后就去干别的,每过一段时间就去瞄一眼进度条,看到 100% 就完成。

同步体现在:等待下载完成通知,但是要在;

非阻塞体现在:等待下载完成通知过程中,去干别的任务了,只是时不时会瞄一眼进度条;【小明必须要在两个任务间切换,关注下载进度】

异步阻塞:小明换了个有下载完成通知功能的软件,下载完成就“叮”一声。不过小明仍然一直等待“叮”的声音(看起来很傻,不是吗)。

异步体现在:下载完成“叮”一声通知;

阻塞体现在:等待下载完成“叮”一声通知过程中,不能做其他任务处理;

异步非阻塞:仍然是那个会“叮”一声的下载软件,小明提交下载任务后就去干别的,听到“叮”的一声就知道完成了。

异步体现在:下载完成“叮”一声通知;

非阻塞体现在:等待下载完成“叮”一声通知过程中,去干别的任务了,只需要接收“叮”声通知即可;【软件处理下载任务,小明处理其他任务,不需关注进度,只需接收软件“叮”声通知,即可】

也就是说,同步/异步是“下载完成消息”通知的方式(机制),而阻塞/非阻塞则是在等待“下载完成消息”通知过程中的状态(能不能干其他任务),在不同的场景下,同步/异步、阻塞/非阻塞的四种组合都有应用。

所以,综上所述,同步和异步仅仅是关注的消息如何通知的机制,而阻塞与非阻塞关注的是等待消息通知时的状态。也就是说,同步的情况下,是由处理消息者自己去等待消息是否被触发,而异步的情况下是由触发机制来通知处理消息者,所以在异步机制中,处理消息者和触发机制之间就需要一个连接的桥梁:

在小明的例子中,这个桥梁就是软件“叮”的声音。

同步/异步与阻塞/非阻塞#

1 同步阻塞形式

效率是最低的,

拿上面的例子来说,就是你专心等待下载完成,什么别的事都不做。

实际程序中:就是未对fd 设置O_NONBLOCK标志位的read/write 操作;

2 异步阻塞形式

异步操作是可以被阻塞住的,只不过它不是在处理消息时阻塞,而是在等待消息通知时被阻塞。

3 同步非阻塞形式

实际上是效率低下的,

想象一下你一边干别的事情一边还需要抬头看下载完成没有,如果把干别的事情和观察下载完成情况的位置看成是程序的两个操作的话,这个程序需要在这两种不同的行为之间来回的切换,效率可想而知是低下的。

4 异步非阻塞形式

效率更高,

因为等待下载完成是你(等待者)的事情,而通知你则是电脑(消息触发机制)的事情,程序没有在两种不同的操作中来回切换。

至此,关于进程线程、同步异步、阻塞非阻塞、并发并行已经讲的差不多了,有讲的不好的地方请大佬指出。同时也谢谢网上大佬的文章帮助我理解了这些概念。

  • 进程间的通信

  • 进程共享内存
    主要参加下面2.2 的例子

2、常用用法总结

2.1 最常用程序

在python中最常用的是用multiprocessing这个模块来实现多进程。

#coding: utf-8
import multiprocessing
import time

def func(msg):
    print "msg:", msg
    time.sleep(3)
    print "end"

if __name__ == "__main__":
    pool = multiprocessing.Pool(processes = 3)
    for i in xrange(4):
        msg = "hello %d" %(i)
        pool.apply_async(func, (msg, ))   #维持执行的进程总数为processes,当一个进程执行完毕后会添加新的进程进去

    print "Mark~ Mark~ Mark~~~~~~~~~~~~~~~~~~~~~~"
    pool.close()
    pool.join()   #调用join之前,先调用close函数,否则会出错。执行完close后不会有新的进程加入到pool,join函数等待所有子进程结束
    print "Sub-process(es) done."
result.png
  • pool.apply_async(func, (msg, )) 是 指异步加载 (看上面解释)
    针对结果,是说,每个进程在调用func 这个函数的时候,不需要等待一个进程调用结束,返回结果之后,再有新的进程调用,而是说,每个都可以进行调用,不用等到正在调用这个函数的进程调用结束再调用(有点绕)。通俗来说就是,msg:hello 1 和end 在输出中并不是紧挨着的。

  • pool.close() 是说不再加入新的进程
    记住就好

  • pool.join() s是说等运行的所有进程结束之后才会运行后面的主程序。
    这个体现在所有的子进程结束之后,才会输出“Sub-process(es) done”

2.2. demon

2.3 主进程和子进程共享内存
import multiprocessing 
from multiprocessing import Manager
# 查看电脑的核数
print(str(multiprocessing.cpu_count()))

def func(i,l):
    temp = [i,i+1]
    l.append(temp)
    print('%s series'%i)
   
if __name__ =='__main__':
    df = pd.DataFrame()
    manager = Manager()
    pool = multiprocessing.Pool(processes =4)
    l= manager.list([])
    for x in range(100):
#        pool.apply_async(func,(x,))
        pool.apply_async(func,(x,l))
#        df = df.append(temp)
        
    pool.close()
    pool.join()
    print(l)
    print('done')

result.png

首先设置一个manager = Manager()
在主进程中先设置一个l 作为list, l= manager.list([])
然后将l 传入每个子进程中pool.apply_async(func,(x,l))
然后在每个子进程中分别对l append
最后在主进程中l 就是所有的apend 加总。

2.4 进程池阻塞和非阻塞的代码

2.4.1. 阻塞

#coding: utf-8
import multiprocessing
import time

def func(msg):
    print "msg:", msg
    time.sleep(3)
    print "end"

if __name__ == "__main__":
    pool = multiprocessing.Pool(processes = 3)
    for i in xrange(4):
        msg = "hello %d" %(i)
        pool.apply(func, (msg, ))   #维持执行的进程总数为processes,当一个进程执行完毕后会添加新的进程进去

    print "Mark~ Mark~ Mark~~~~~~~~~~~~~~~~~~~~~~"
    pool.close()
    pool.join()   #调用join之前,先调用close函数,否则会出错。执行完close后不会有新的进程加入到pool,join函数等待所有子进程结束
    print "Sub-process(es) done."
image.png

2.4.2 非阻塞

import multiprocessing
import time

def func(msg):
    print "msg:", msg
    time.sleep(3)
    print "end"
    return "done" + msg

if __name__ == "__main__":
    pool = multiprocessing.Pool(processes=4)
    result = []
    for i in xrange(3):
        msg = "hello %d" %(i)
        result.append(pool.apply_async(func, (msg, )))
    pool.close()
    pool.join()
    for res in result:
        print ":::", res.get()
    print "Sub-process(es) done."
image.png

未完待续

参考资料

1、廖雪峰
2、理论篇
3、综合篇
4、实战程序篇
5、故事篇

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342