多進(jìn)程和多線程編程

多任務(wù)的實(shí)現(xiàn)方式:

  • 多進(jìn)程模式
  • 多線程模式
  • 多進(jìn)程 + 多線程 模式
    python即支持多進(jìn)程拱绑,又支持多線程,如下進(jìn)行介紹果港。

多進(jìn)程

操作系統(tǒng)fork()系統(tǒng)調(diào)用復(fù)制當(dāng)前進(jìn)程廉羔,并且在父進(jìn)程和子進(jìn)程中返回,父進(jìn)程中返回fork出的子進(jìn)程ID塘揣, 子進(jìn)程中返回0;
一個(gè)父進(jìn)程可以fork很多子進(jìn)程包雀;
子進(jìn)程可以通過(guò)getppid()拿到父進(jìn)程ID;任何進(jìn)程都可以通過(guò)getpid()拿取當(dāng)前進(jìn)程ID;

python的os模塊封閉了常見(jiàn)的系統(tǒng)調(diào)用,其中就包括fork.

#/usr/bin/env python
# _*_ encoding: utf-8 _*_

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)

運(yùn)行結(jié)果:

Process (19929) start...
I (19929) just created a child process (19930).
I am child process (19930) and my parent is 19929.

由于Windows沒(méi)有fork調(diào)用亲铡,上面的代碼在Windows上無(wú)法運(yùn)行才写。

multiprocess--跨平臺(tái)的多進(jìn)程支持模塊

1.Process實(shí)例

#/usr/bin/env python
# _*_ encoding: utf-8 _*_

from multiprocessing import Process
import os

def run_proc(name):
    print 'Run child process %s (%s)...' % (name, os.getpid())

if __name__ == '__main__':
    print 'Parent process %s.' % os.getpid()
    p = Process(target=run_proc, args=('test',))
    print 'Process will start'
    p.start()  #啟動(dòng)子進(jìn)程
    p.join()   #等待子進(jìn)程結(jié)束再向下執(zhí)行
    print 'Process end'

運(yùn)行結(jié)果

Parent process 24556.
Process will start
Run child process test (24557)...
Process end

2.Pool實(shí)例--進(jìn)程池實(shí)現(xiàn)

#!/usr/bin/env python
# _*_ encoding: utf-8 _*_

from multiprocessing import Pool
import os, time, random

def long_time_task(name):
    print 'Run task %s (%s)...' % (name, os.getpid())
    start = time.time()
    time.sleep(random.random() * 3)
    end = time.time()
    print 'Task %s runs %0.2f seconds.' % (name, (end - start))

if __name__ == '__main__':
    print 'Parent process %s.' % os.getpid()
    p = Pool()
    for i in range(5):
        p.apply_async(long_time_task, args=(i, ))
    print 'Waiting for all subprocesses done...'
    p.close()  #調(diào)用close()之后就不能繼續(xù)添加新的Process了
    p.join()
    print 'All subprocesses done.'

運(yùn)行結(jié)果

Parent process 27577.
Waiting for all subprocesses done...
Run task 0 (27579)...
Run task 1 (27580)...
Run task 2 (27581)...
Run task 3 (27582)...
Task 1 runs 0.15 seconds.
Run task 4 (27580)...
Task 3 runs 1.40 seconds.
Task 4 runs 1.27 seconds.
Task 0 runs 1.96 seconds.
Task 2 runs 2.04 seconds.
All subprocesses done.

請(qǐng)注意輸出的結(jié)果,task 0奖蔓,1赞草,2,3是立刻執(zhí)行的吆鹤,而task 4要等待前面某個(gè)task完成后才執(zhí)行厨疙,這是因?yàn)镻ool的默認(rèn)大小在我的電腦上是4,因此疑务,最多同時(shí)執(zhí)行4個(gè)進(jìn)程沾凄。這是Pool有意設(shè)計(jì)的限制,并不是操作系統(tǒng)的限制知允。(Pool的默認(rèn)大小是CPU的核數(shù))撒蟀,可以根據(jù)pool的第一個(gè)參數(shù)進(jìn)行修改:
p = Pool(5)

進(jìn)程間通信

Python中multiprocessing模塊包裝了底層的機(jī)制,提供了Queue温鸽、Pipes等方式來(lái)進(jìn)行進(jìn)程間數(shù)據(jù)交換保屯。
如何以Queue為示例:

#!/usr/bin/env python
# _*_ encoding: utf-8 _*_

from multiprocessing import Process, Queue
import os, time, random

# 寫進(jìn)程執(zhí)行的代碼:
def write(q):
    for value in ['A', 'B', 'C']:
        print 'Put %s to queue...' % value
        q.put(value)
        time.sleep(random.random())

# 讀進(jìn)程執(zhí)行的代碼:
def read(q):
    while True:
        value = q.get(True)
        print 'Get %s from queue.' % value

if __name__=='__main__':
    # 父進(jìn)程創(chuàng)建Queue,并傳給各個(gè)子進(jìn)程
    q = Queue()
    pw = Process(target=write, args=(q,))
    pr = Process(target=read, args=(q,))
    pw.start()
    pr.start()
    # 等待PW結(jié)束
    pw.join()
    # 強(qiáng)行結(jié)束pr進(jìn)程
    pr.terminate()

結(jié)果:
Put A to queue...
Get A from queue.
Put B to queue...
Get B from queue.
Put C to queue...
Get C from queue.

多線程

python標(biāo)準(zhǔn)庫(kù)通過(guò)thread和threading實(shí)現(xiàn)多線程嗤朴;thread是低級(jí)模塊配椭;threading是高級(jí)模塊;

#!/usr/bin/env python
# _*_ encoding: utf-8 _*_

import time,threading

# 新線程執(zhí)行的代碼
def loop():
    print 'thread %s is running...' % threading.current_thread().name
    n = 0
    while n < 5:
        n = n + 1
        print 'thread %s >>> %s' % (threading.current_thread().name, n)
        time.sleep(1)
    print 'thread %s ended.' % threading.current_thread().name

print 'thread %s is running...' % threading.current_thread().name
t = threading.Thread(target=loop, name='LoopThread')
t.start()
t.join()
print 'thread %s ended.' % threading.current_thread().name

結(jié)果:
thread MainThread is running...
thread LoopThread is running...
thread LoopThread >>> 1
thread LoopThread >>> 2
thread LoopThread >>> 3
thread LoopThread >>> 4
thread LoopThread >>> 5
thread LoopThread ended.
thread MainThread ended.

多線程程序需要解決的一個(gè)問(wèn)題就是多線程共享變量雹姊,造成修改混亂股缸。
需要通過(guò)threading.Lock()進(jìn)行加鎖解鎖。

寫在最后的坑:
python有一個(gè)GIL鎖吱雏,Global Interpreter Lock, 使所有的python多線程只能交替執(zhí)行敦姻,只能在1核心上跑瘾境。。镰惦。
在Python中迷守,可以使用多線程,但不要指望能有效利用多核旺入。如果一定要通過(guò)多線程利用多核兑凿,那只能通過(guò)C擴(kuò)展來(lái)實(shí)現(xiàn),不過(guò)這樣就失去了Python簡(jiǎn)單易用的特點(diǎn)茵瘾。
不過(guò)礼华,也不用過(guò)于擔(dān)心,Python雖然不能利用多線程實(shí)現(xiàn)多核任務(wù)拗秘,但可以通過(guò)多進(jìn)程實(shí)現(xiàn)多核任務(wù)圣絮。多個(gè)Python進(jìn)程有各自獨(dú)立的GIL鎖,互不影響雕旨。

所以Python推薦使用多進(jìn)程...

python支持分布式進(jìn)程

multiprocessing.managers子模塊支持把多進(jìn)程分布到多臺(tái)機(jī)器上;

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末扮匠,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子凡涩,更是在濱河造成了極大的恐慌棒搜,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,816評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件突照,死亡現(xiàn)場(chǎng)離奇詭異帮非,居然都是意外死亡氧吐,警方通過(guò)查閱死者的電腦和手機(jī)讹蘑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)筑舅,“玉大人座慰,你說(shuō)我怎么就攤上這事〈浼穑” “怎么了版仔?”我有些...
    開(kāi)封第一講書人閱讀 158,300評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)误墓。 經(jīng)常有香客問(wèn)我蛮粮,道長(zhǎng),這世上最難降的妖魔是什么谜慌? 我笑而不...
    開(kāi)封第一講書人閱讀 56,780評(píng)論 1 285
  • 正文 為了忘掉前任然想,我火速辦了婚禮,結(jié)果婚禮上欣范,老公的妹妹穿的比我還像新娘变泄。我一直安慰自己令哟,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,890評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布妨蛹。 她就那樣靜靜地躺著屏富,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蛙卤。 梳的紋絲不亂的頭發(fā)上狠半,一...
    開(kāi)封第一講書人閱讀 50,084評(píng)論 1 291
  • 那天,我揣著相機(jī)與錄音颤难,去河邊找鬼典予。 笑死,一個(gè)胖子當(dāng)著我的面吹牛乐严,可吹牛的內(nèi)容都是我干的瘤袖。 我是一名探鬼主播,決...
    沈念sama閱讀 39,151評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼昂验,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼捂敌!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起既琴,我...
    開(kāi)封第一講書人閱讀 37,912評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤占婉,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后甫恩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體逆济,經(jīng)...
    沈念sama閱讀 44,355評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,666評(píng)論 2 327
  • 正文 我和宋清朗相戀三年磺箕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了奖慌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,809評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡松靡,死狀恐怖简僧,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情雕欺,我是刑警寧澤岛马,帶...
    沈念sama閱讀 34,504評(píng)論 4 334
  • 正文 年R本政府宣布,位于F島的核電站屠列,受9級(jí)特大地震影響啦逆,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜笛洛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,150評(píng)論 3 317
  • 文/蒙蒙 一夏志、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧撞蜂,春花似錦盲镶、人聲如沸侥袜。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)枫吧。三九已至,卻和暖如春宇色,著一層夾襖步出監(jiān)牢的瞬間九杂,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,121評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工宣蠕, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留例隆,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,628評(píng)論 2 362
  • 正文 我出身青樓抢蚀,卻偏偏與公主長(zhǎng)得像镀层,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子皿曲,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,724評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容

  • 進(jìn)程與線程的區(qū)別 現(xiàn)在唱逢,多核CPU已經(jīng)非常普及了,但是屋休,即使過(guò)去的單核CPU坞古,也可以執(zhí)行多任務(wù)。由于CPU執(zhí)行代碼...
    蘇糊閱讀 763評(píng)論 0 2
  • 本系列主要學(xué)習(xí)Python的基本使用和語(yǔ)法知識(shí)劫樟,后續(xù)可能會(huì)圍繞著AI學(xué)習(xí)展開(kāi)痪枫。Python3 (1) Python...
    猿來(lái)如癡閱讀 1,446評(píng)論 0 5
  • 上了一天的課奶陈,閑下來(lái)看綜藝節(jié)目。無(wú)意中看到了高娃老師朗讀的《寫給母親》虑绵。 眼淚簌簌而落尿瞭。我想起了我的父親,離開(kāi)我已...
    小鬧騰1992閱讀 253評(píng)論 1 0
  • 郭相麟 我們對(duì)走進(jìn)生命里的朋友“好”是應(yīng)該的翅睛,“好”需要謙和,“好”需要容納黑竞,至于別人對(duì)于我們給予的“好”捕发,“好...
    郭相麟閱讀 163評(píng)論 0 0
  • 顧惜:提前一天到,聽(tīng)娜娜彈琴很魂,手舞足蹈的與三姐聊天(一只手端著冰茶)扎酷,軍綠羽絨服,黑色休閑褲遏匆,淺棕色毛衣法挨,深藍(lán)運(yùn)動(dòng)...
    雪蝰閱讀 162評(píng)論 3 6