14-多線程與多進(jìn)程

多線程

目前市面上常見(jiàn)的系統(tǒng),如windows、mac os、Linux都支持多線程

什么是多任務(wù)

操作系統(tǒng)同時(shí)執(zhí)行多個(gè)任務(wù)

單核CPU如何實(shí)現(xiàn)多任務(wù)吉嚣?

表面看,每個(gè)任務(wù)都是同時(shí)執(zhí)行蹬铺,實(shí)際上每個(gè)任務(wù)都在輪詢著執(zhí)行尝哆;
只是因?yàn)镃PU調(diào)度和執(zhí)行速度太快,導(dǎo)致我們感覺(jué)是所有任務(wù)都在同時(shí)執(zhí)行

多核CPU如何實(shí)現(xiàn)多任務(wù)甜攀?

當(dāng)任務(wù)數(shù)小于CPU核心數(shù)時(shí)秋泄,是真正的多任務(wù)
當(dāng)任務(wù)數(shù)大于CPU核心數(shù)時(shí),多余的任務(wù)會(huì)再次被分配赴邻,分配到的CPU進(jìn)行輪詢執(zhí)行

并發(fā)與并行

并發(fā):表面看時(shí)一起執(zhí)行印衔,但是任務(wù)數(shù)多余CPU核心數(shù)
并行:一起執(zhí)行啡捶,但是任務(wù)數(shù)小于CPU數(shù)

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

1.多進(jìn)程方式 多操作系統(tǒng)而言姥敛,一個(gè)任務(wù)就是一個(gè)進(jìn)程
2.多線程方式
3.協(xié)程方式
4.多進(jìn)程+多線程方式

python中的多進(jìn)程

multiprocessing 多進(jìn)程

from multiprocessing import Process

import time


def func():
    while True:
        print("這也是一個(gè)python進(jìn)程")
        time.sleep(1.5)

if __name__ == '__main__':
    print("父進(jìn)程啟動(dòng)...")
    p = Process(target=func)
    p.start()
    while True:
        print("這是一個(gè)python進(jìn)程")
        time.sleep(1)

帶有參數(shù)的多進(jìn)程

from multiprocessing import Process

import time


def func(str):
    while True:
        print("這也是一個(gè)%s進(jìn)程"%str)
        time.sleep(1.5)

if __name__ == '__main__':
    print("父進(jìn)程啟動(dòng)...")
    p = Process(target=func, args=("python",))
    p.start()
    while True:
        print("這是一個(gè)python進(jìn)程")
        time.sleep(1)

多進(jìn)程中的變量

.join() 表示父進(jìn)程等待子進(jìn)程結(jié)束再繼續(xù)執(zhí)行

每個(gè)進(jìn)程都有自己的一套代碼段、數(shù)據(jù)段和堆棧段瞎暑,互不干擾彤敛;
也就是說(shuō)父進(jìn)程中的全局變量會(huì)在子進(jìn)程創(chuàng)建時(shí)備份一份与帆,
如果在子進(jìn)程中進(jìn)行更改不會(huì)影響父進(jìn)程中的變量;
同樣如果父進(jìn)程在創(chuàng)建了子進(jìn)程后再對(duì)全局變量進(jìn)行修改墨榄,同樣不會(huì)對(duì)子進(jìn)程的變量造成影響

Pocess中傳遞參數(shù)必須為可迭代對(duì)象

from multiprocessing import Process
import time

num = 100


def func(num):
    print("子進(jìn)程啟動(dòng)...")
    time.sleep(1)
    num += 1
    print(num)
    print("子進(jìn)程結(jié)束...")


if __name__ == '__main__':

    print("父進(jìn)程啟動(dòng)...")
    p = Process(target=func, args=(num,))
    # 此時(shí)子進(jìn)程已創(chuàng)建玄糟,再修改父進(jìn)程中的全局變量將不會(huì)影響子進(jìn)程
    num += 2
    p.start()

    print("父進(jìn)程結(jié)束...%d" % num)

進(jìn)程池

1.進(jìn)程池需要導(dǎo)入 multiprocessing 中的Pool
2.創(chuàng)建進(jìn)程池時(shí)Pool()中的參數(shù)表示同時(shí)啟動(dòng)的進(jìn)程數(shù)
如果不寫(xiě)則表示本機(jī)的邏輯核心數(shù)
3.進(jìn)程池中進(jìn)程啟動(dòng)不用寫(xiě) start 語(yǔ)句
4.進(jìn)程池必須先關(guān)閉才能join
5.進(jìn)程池join后,父進(jìn)程會(huì)等待池內(nèi)所有進(jìn)程執(zhí)行完畢再向下執(zhí)行
6.進(jìn)程池內(nèi)的進(jìn)程啟動(dòng)順序由操作系統(tǒng)來(lái)決定

from multiprocessing import Pool
import time, random


def func(num):
    print("子進(jìn)程%d啟動(dòng)" % num)
    start = time.time()
    time.sleep(random.choice([1, 2, 3]))
    end = time.time()
    print("子進(jìn)程%d結(jié)束袄秩,耗時(shí)%d秒" % (num, end-start))


def func1():
    print("我是一個(gè)子進(jìn)程阵翎,我負(fù)責(zé)計(jì)算1+1=2")


if __name__ == '__main__':
    print("父進(jìn)程啟動(dòng)")
    # Pool中的參數(shù)表示同時(shí)啟動(dòng)進(jìn)程的數(shù)量,如果不寫(xiě)則表示本機(jī)邏輯核心數(shù)
    # 進(jìn)程池中的進(jìn)程啟動(dòng)順序由系統(tǒng)來(lái)決定
    pp = Pool(2)
    # # 此處為用for循環(huán)建立多個(gè)子進(jìn)程之剧,但是子進(jìn)程的功能都相同
    # for i in range(10):
    #     pp.apply_async(func, args=(i,))

    # 此處為單個(gè)建立子進(jìn)程郭卫,子進(jìn)程的功能可以不同
    pp.apply_async(func, args=(1,))
    pp.apply_async(func1)

    # 進(jìn)程池中進(jìn)程不需要寫(xiě)start語(yǔ)句
    # 進(jìn)程池進(jìn)行join時(shí)必須先關(guān)閉
    pp.close()
    # 進(jìn)程池join后父進(jìn)程會(huì)等待進(jìn)程池中所有程序結(jié)束才繼續(xù)執(zhí)行
    pp.join()
    print("父進(jìn)程結(jié)束")

多線程混亂

多個(gè)線程對(duì)同一數(shù)據(jù)進(jìn)行更改時(shí),次數(shù)越大背稼,發(fā)生錯(cuò)誤或線程混亂的幾率越大

import threading
num = 0


def run(n):
    global num
    for i in range(1000000):
        num = num + n
        num = num - n
        # print(num)


if __name__ == '__main__':
    t1 = threading.Thread(target=run, args=(6,))
    t2 = threading.Thread(target=run, args=(9,))
    t1.start()
    t2.start()
    t1.join()
    t2.join()

    print("num = ",num)

鎖對(duì)象

為了確保一段代碼只能由一個(gè)線程從頭到尾的完整執(zhí)行
我們引入了鎖對(duì)象贰军,來(lái)限制進(jìn)行的并發(fā)執(zhí)行,避免多線程并發(fā)引起的數(shù)據(jù)混亂
但是會(huì)大大的降低效率

import threading

# 所對(duì)象
lock = threading.Lock()
num = 0


def run(n):
    global num
    for i in range(1000000):
        """
        # 第一種寫(xiě)法
        # 加鎖
        lock.acquire()
        num += n
        num -= n
        # 解鎖
        lock.release()
        """
        # 第二種寫(xiě)法
        with lock:
            num += n
            num -= n


if __name__ == '__main__':
    t1 = threading.Thread(target=run, args=(10,))
    t2 = threading.Thread(target=run, args=(4,))
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print("num =", num)

信號(hào)量:Semaphore

限定多線程并發(fā)數(shù)量
線程結(jié)束數(shù)量:Barrier
限定多線程的結(jié)束數(shù)量,如果數(shù)量不足蟹肘,則等待词疼,
直到數(shù)量滿足要求再結(jié)束

如果二者同時(shí)使用,注意并發(fā)數(shù)量應(yīng)大于結(jié)束數(shù)量
否則線程無(wú)法結(jié)束帘腹,無(wú)法繼續(xù)并發(fā)贰盗,程序會(huì)一直處于等待中

import threading,time
# 設(shè)置多線程并發(fā)數(shù)量
sem = threading.Semaphore(4)
# 設(shè)置指定數(shù)量結(jié)束
bar = threading.Barrier(3)


def run():
    with sem:
        print("%s--start"%threading.current_thread().name)
        time.sleep(1)
        bar.wait()
        print("%s--end"%threading.current_thread().name)



if __name__ == '__main__':
    for i in range(10):
        t = threading.Thread(target=run)
        t.start()

初學(xué)筆記,僅供參考

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末阳欲,一起剝皮案震驚了整個(gè)濱河市童太,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌胸完,老刑警劉巖书释,帶你破解...
    沈念sama閱讀 212,718評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異赊窥,居然都是意外死亡爆惧,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)锨能,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)扯再,“玉大人,你說(shuō)我怎么就攤上這事址遇∠ㄗ瑁” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,207評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵倔约,是天一觀的道長(zhǎng)秃殉。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么钾军? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,755評(píng)論 1 284
  • 正文 為了忘掉前任鳄袍,我火速辦了婚禮,結(jié)果婚禮上吏恭,老公的妹妹穿的比我還像新娘拗小。我一直安慰自己,他們只是感情好樱哼,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布哀九。 她就那樣靜靜地躺著,像睡著了一般搅幅。 火紅的嫁衣襯著肌膚如雪勾栗。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 50,050評(píng)論 1 291
  • 那天盏筐,我揣著相機(jī)與錄音围俘,去河邊找鬼。 笑死琢融,一個(gè)胖子當(dāng)著我的面吹牛界牡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播漾抬,決...
    沈念sama閱讀 39,136評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼宿亡,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了纳令?” 一聲冷哼從身側(cè)響起挽荠,我...
    開(kāi)封第一講書(shū)人閱讀 37,882評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎平绩,沒(méi)想到半個(gè)月后圈匆,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,330評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡捏雌,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評(píng)論 2 327
  • 正文 我和宋清朗相戀三年跃赚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片性湿。...
    茶點(diǎn)故事閱讀 38,789評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡纬傲,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出肤频,到底是詐尸還是另有隱情叹括,我是刑警寧澤,帶...
    沈念sama閱讀 34,477評(píng)論 4 333
  • 正文 年R本政府宣布宵荒,位于F島的核電站汁雷,受9級(jí)特大地震影響净嘀,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜摔竿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望少孝。 院中可真熱鬧继低,春花似錦、人聲如沸稍走。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,864評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)婿脸。三九已至粱胜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間狐树,已是汗流浹背焙压。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,099評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留抑钟,地道東北人涯曲。 一個(gè)月前我還...
    沈念sama閱讀 46,598評(píng)論 2 362
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像在塔,于是被迫代替她去往敵國(guó)和親幻件。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評(píng)論 2 351

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