詳解Python中的多線程、線程鎖、線程變量 - threading梅割、Thread霜第、Lock與ThreadLocal詳解

其他關(guān)于Python的總結(jié)文章請訪問:http://www.reibang.com/nb/47435944

詳解Python中的多線程、線程鎖户辞、線程變量 - threading泌类、Thread、Lock與ThreadLocal詳解

關(guān)于多進(jìn)程的內(nèi)容請參考:<>

一個進(jìn)程可以包含多個線程底燎,而且至少必須要有一個線程刃榨,這個線程被稱為主線程,在Python中的名字為 MainThread双仍。進(jìn)程與線程最大的不同在于枢希,進(jìn)程的信息時各自的,而(同一個進(jìn)程下的)線程的信息是公用的朱沃,即他們都處理苞轿、使用所在進(jìn)程的信息數(shù)據(jù)等。

可以使用Python中的threading模塊進(jìn)行線程管理于操作为流。使用 threading.current_thread() 獲取當(dāng)前所在線程呕屎,使用線程實例的name屬性獲取線程的名字。

使用Thread創(chuàng)建多線程

一個python運行起來后對應(yīng)著一個進(jìn)程敬察,這個進(jìn)程的的主線程即 MainThread秀睛,使用Thread可以創(chuàng)建新的線程,創(chuàng)建時使用參數(shù) target 綁定線程運行的目標(biāo)莲祸,使用 name 參數(shù)為線程定義一個名字蹂安。

Thread的實例有的常用方法:

  • start:開始執(zhí)行這個線程
  • join:等待線程執(zhí)行結(jié)束

一個例子:

import time, random, threading


def print_time():
    time.sleep(random.random())
    print("I'm thread {}, time now is {}".format(threading.current_thread().name, time.time()))


print("The main thread is {}".format(threading.current_thread().name))
thread1 = threading.Thread(target=print_time, name="New Thread 1")
thread2 = threading.Thread(target=print_time, name="New Thread 2")
thread3 = threading.Thread(target=print_time, name="New Thread 3")

thread1.start()
thread2.start()
thread3.start()

thread1.join()
thread2.join()
thread3.join()

得到的結(jié)果是隨機(jī)的:

The main thread is MainThread
I'm thread New Thread 3, time now is 1607256751.4239407
I'm thread New Thread 1, time now is 1607256751.8748183
I'm thread New Thread 2, time now is 1607256751.9063895

使用鎖Lock修改數(shù)據(jù)

由于(同一個進(jìn)程下的)多個線程使用的是同一套數(shù)據(jù),所以如果多個線程同時訪問一個數(shù)據(jù)就會造成沖突锐帜,解決的方法是使用線程鎖田盈,在某個線程修改這個數(shù)據(jù)的時候,它獲得一把鎖缴阎,只有獲得鎖的這個線程有權(quán)利修改這個數(shù)據(jù)允瞧,等修改完成后再釋放鎖,這樣就可以保證在一個時間只有一個線程修改這個數(shù)據(jù)蛮拔。如果多個線程都想請求得到鎖述暂,他們會排隊獲得。

Python中使用threading.Lock來完成建炫,一個Lock實例常用的的方法有:

  • acquire:請求獲得鎖
  • relaese:釋放鎖

為例確保一個線程在使用完后一定會釋放鎖畦韭,通常使用try...final...語句,將釋放鎖的代碼放在finally塊里肛跌。

一個例子:一個線程要給一個數(shù)據(jù)加一艺配,一個線程要給同一個數(shù)據(jù)減一:

import time, random, threading

number = 0
lock = threading.Lock()


def add_one():
    global number
    for i in range(20):
        lock.acquire()
        print("I'm thread {}, I acquired the lock.".format(threading.current_thread().name))
        try:
            number += 1
        finally:
            lock.release()
            print("I'm thread {}, I realised the lock.".format(threading.current_thread().name))


def minus_one():
    global number
    for i in range(20):
        lock.acquire()
        print("I'm thread {}, I acquired the lock.".format(threading.current_thread().name))
        try:
            number -= 1
        finally:
            lock.release()
            print("I'm thread {}, I realised the lock.".format(threading.current_thread().name))


thread_add = threading.Thread(target=add_one, name="Thread ADD")
thread_minus = threading.Thread(target=minus_one, name="Thread MINUS")

thread_add.start()
thread_minus.start()

thread_add.join()
thread_minus.join()

使用ThreadLocal創(chuàng)建進(jìn)程局部變量

設(shè)想如果有多個線程察郁,它們都要處理自己的一個變量,但是又想進(jìn)行對于該變量的信息交換转唉,這樣的情況下皮钠,可以使用一個全局變量來記錄每個線程的局部變量(比如一個字典),顯然是很麻煩的酝掩,于是可以使用ThreadLocal來處理線程的局部變量鳞芙。

一個例子:兩個線程都有各自的變量number

import threading

local_variable = threading.local()


def print_number():
    number = local_variable.number
    print("I'm thread {}, I'm processing my number {}".format(threading.current_thread().name, number))


def set_number(num):
    local_variable.number = num
    print_number()


thread1 = threading.Thread(target=set_number, args=(1,), name="Thread 1")
thread2 = threading.Thread(target=set_number, args=(2,), name="Thread 2")

thread1.start()
thread2.start()
thread1.join()
thread2.join()

得到的結(jié)果如下:

I'm thread Thread 1, I'm processing my number 1
I'm thread Thread 2, I'm processing my number 2
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市期虾,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌驯嘱,老刑警劉巖镶苞,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異鞠评,居然都是意外死亡茂蚓,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進(jìn)店門剃幌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來聋涨,“玉大人,你說我怎么就攤上這事负乡‰拱祝” “怎么了?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵抖棘,是天一觀的道長茂腥。 經(jīng)常有香客問我,道長切省,這世上最難降的妖魔是什么最岗? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮朝捆,結(jié)果婚禮上般渡,老公的妹妹穿的比我還像新娘。我一直安慰自己芙盘,他們只是感情好驯用,可當(dāng)我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著何陆,像睡著了一般晨汹。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上贷盲,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天淘这,我揣著相機(jī)與錄音剥扣,去河邊找鬼。 笑死铝穷,一個胖子當(dāng)著我的面吹牛钠怯,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播曙聂,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼晦炊,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了宁脊?” 一聲冷哼從身側(cè)響起断国,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎榆苞,沒想到半個月后稳衬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡坐漏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年薄疚,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赊琳。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡街夭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出躏筏,到底是詐尸還是另有隱情板丽,我是刑警寧澤,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布寸士,位于F島的核電站檐什,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏弱卡。R本人自食惡果不足惜乃正,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望婶博。 院中可真熱鬧瓮具,春花似錦、人聲如沸凡人。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽挠轴。三九已至传睹,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間岸晦,已是汗流浹背欧啤。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工睛藻, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人邢隧。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓店印,卻偏偏與公主長得像,于是被迫代替她去往敵國和親倒慧。 傳聞我的和親對象是個殘疾皇子按摘,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,629評論 2 354

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