2019-05-10_day_18_python多線程_完整版總結(jié)


操作系統(tǒng)分時技術(shù)(對于進(jìn)程而言):

將處理機(jī)的運行時間分成很短的時間片,按時間片輪流把處理機(jī)分配給各聯(lián)機(jī)作業(yè)使用萤悴。

特點:

多路性璧疗,交互性,獨立性秧倾,及時性

目標(biāo):

對用戶響應(yīng)的及時性怨酝,即不至于用戶等待每一個命令的處理時間過長


進(jìn)程的定義:

執(zhí)行中的程序稱為進(jìn)程;

程序和進(jìn)程的區(qū)別:

程序是指令的集合那先,是進(jìn)程運行的靜態(tài)描述文本农猬;進(jìn)程是程序的一次執(zhí)行活動,屬于動態(tài)概念售淡。

進(jìn)程的缺點:

進(jìn)程只能在一個時間干一件事斤葱;
進(jìn)程在執(zhí)行過程中如果阻塞,例如等待輸入揖闸,整個進(jìn)程就會掛起揍堕,即使進(jìn)程中有些工作不依賴輸入的數(shù)據(jù),也將無法執(zhí)行
例子:若QQ是一個只能在同一時間干一件事的獨立進(jìn)程的話汤纸,則監(jiān)聽鍵盤輸入衩茸,監(jiān)聽他人發(fā)送信息,顯示他人發(fā)送的信息將無法同步實現(xiàn)


線程的定義(thread):

線程是操作系統(tǒng)能夠進(jìn)行運算調(diào)度的最小單位贮泞。它被包含在進(jìn)程中楞慈,是進(jìn)程中的實際運作單位。一條進(jìn)程指的是進(jìn)程中一個單一順序的控制流啃擦,一個進(jìn)程中可以并發(fā)多個線程囊蓝,每條線程并行執(zhí)行不同的任務(wù)

進(jìn)程和線程的區(qū)別:

1.線程是共享進(jìn)程的地址空間來創(chuàng)建的,進(jìn)程有自己的地址空間令蛉。
2.線程可以直接接受它所屬進(jìn)程的數(shù)據(jù)段聚霜,而進(jìn)程需要復(fù)制它父進(jìn)程的數(shù)據(jù)段不能直接調(diào)用。
3.線程可以在所屬進(jìn)程中直接與其它線程進(jìn)行通訊,進(jìn)程必須使用進(jìn)程間通信來與其它進(jìn)程進(jìn)行通訊俯萎。
4.新的線程很容易創(chuàng)建,新的進(jìn)程需要復(fù)制其父進(jìn)程运杭。
5.對于相同進(jìn)程而言夫啊,線程可以遠(yuǎn)超過其它線程對其進(jìn)行控制;進(jìn)程的控制力只有父進(jìn)程大于子進(jìn)程辆憔。
6.修改主線程(取消撇眯,修改優(yōu)先級等)可能會影響進(jìn)程中其它線程;修改父進(jìn)程不能影響子進(jìn)程虱咧。


線程的并發(fā)機(jī)制:

線程有開始熊榛,順序執(zhí)行和結(jié)束三個部分。還有一個指令指針用于記錄運行的位置腕巡,
線程運行被搶占(中斷)玄坦,被暫時的掛起(睡眠),讓其它線程運行(讓步)绘沉。線程在進(jìn)程中共享數(shù)據(jù)煎楣。

線程的并發(fā)本質(zhì):

單cpu中,并行的實現(xiàn)是通過規(guī)定線程運行時間片并進(jìn)行讓步來實現(xiàn)的车伞。

線程并發(fā)的風(fēng)險與解決:

競態(tài)條件(race condition)的產(chǎn)生(數(shù)據(jù)訪問的順序不一樣)择懂,導(dǎo)致數(shù)據(jù)結(jié)果的不一致。
使用線程庫的同步語句來控制線程的執(zhí)行和數(shù)據(jù)的訪問另玖。


python中多線程的實現(xiàn):

方法1直接創(chuàng)建線程對象

import time
from datatime import datatime
import threading #python中提供線程相關(guān)操作的庫
# 每個進(jìn)程默認(rèn)都有一個線程困曙,這個線程叫主線程;其他的線程都叫子線程
def download(file_name): #模擬線程
    print("開始下載%s"%file_name,datatime.now()) # 打印當(dāng)前時間谦去,線程起始時間
    time.sleep(5) #線程掛起5秒
    print("%s下載完成"%file_name,datatime.now()) # 打印當(dāng)前時間慷丽,線程終止時間

# 用模擬單線程進(jìn)行對比
# 1.單線程下載兩個電影:
# 在一個線程中下載兩個電影:時間是兩個電影下載的總和
download("復(fù)聯(lián)4")
download("007")

# 2.線程模塊
# 1)current_thread 函數(shù) - 獲取當(dāng)前線程
print(threading.current_thread()) #當(dāng)前打印的是主進(jìn)程 

# 2)Thread類
'''
Thread類的對象就是線程。所以需要子線程就創(chuàng)建這個類的對象
Thread(target,args,kwargs)
target - 函數(shù)鳄哭,需要在當(dāng)前創(chuàng)建的子線程中去調(diào)用的函數(shù)
args/kwargs - 調(diào)用target中的函數(shù)需要的實參列表
'''
# a.創(chuàng)建線程對象
t1 = threading.Thread(target=download, args("復(fù)聯(lián)4",)) #元組寫法
# t1 = threading.Thread(target=download, kwargs = {"film_name":"復(fù)聯(lián)4"})
t2 = threading.Thread(target=download, args("007",))

# b.開始執(zhí)行子線程中的任務(wù):線程對象.start()
'''
通過start方法盈魁,在子線程中去調(diào)用target對應(yīng)的函數(shù)
'''
t1.start()
t2.start()

方法2.創(chuàng)建自己的線程類

from threading import *
import time
from datatime import datatime

# 1.創(chuàng)建自己的線程類
'''
1) 聲明一個類繼承Thread
2) 實現(xiàn)run方法,這個方法中的任務(wù)就是需要在子線程中執(zhí)行的任務(wù)
   注意:一個進(jìn)程中如果有多個線程窃诉,程序會在所有的線程都結(jié)束的時候才結(jié)束杨耙;發(fā)生異常崩潰其實崩潰的是線程
'''
class DownloadThread(Thread):
    def __init__(self, file_name):
        super().__init__()
        self.film_name = film_name
    
    def run(self):
    # print(current_thread())
    # print("在子線程中執(zhí)行的代碼")
    print("開始下載:%s"%self.film_name, datatime.now())
    # print([1, 2][3]) #檢驗線程崩潰后其他線程是否正常使用
    time.sleep(3)
    print("結(jié)束下載%s"%self.film_name, datatime.now())
# 3) 用子類直接創(chuàng)建線程對象
t1 = DownloadThread('復(fù)聯(lián)4')
t2 = DownloadThread('長江7號')
# 4) 通過start去執(zhí)行子線程中的任務(wù)
t1.start()
t2.start()
# 注意:t1.run()    # 不能直接調(diào)用run方法,因為這樣調(diào)用不會在子線程中執(zhí)行任務(wù)會在主線程中調(diào)用,詳情看源碼和結(jié)果
# t2.run()
'''
<_MainThread(MainThread, started 360)>
開始下載: 復(fù)聯(lián)4 2019-05-10 11:50:05.386988
結(jié)束下載: 復(fù)聯(lián)4 2019-05-10 11:50:08.387990
<_MainThread(MainThread, started 360)>
開始下載: 長江7號 2019-05-10 11:50:08.387990
結(jié)束下載: 長江7號 2019-05-10 11:50:11.388084
'''
while True:
    input('>>>:')# 主線程調(diào)用與子線程互不干擾

線程控制join方法

from threading import Thread
from datetime import datetime
import time
from random import randint

class DownloadThread(Thread):
    def __init__(self, name, time):
        super().__init__()
        self.name = name
        self.time = time
    
    def run(self):
        print("開始下載:%s"%self.name)
        time.sleep(self.time)
        print("下載結(jié)束:%s"%self.name)

t1 = DownloadThread("abc", 5)
t2 = DownloadThread("def", 7)

t2.start()
t1.start()

# 1.join
'''
如果希望某個任務(wù)是在某個線程結(jié)束后才執(zhí)行飘痛,那就將這個任務(wù)的代碼放在對應(yīng)線程對象調(diào)用join方法的后面
'''
t1.join()
t2.join()
print("下載完成") #實現(xiàn)需求:兩個完成時間不同的任務(wù)均完成后進(jìn)行打印

'''
需求:一個任務(wù)完成后再執(zhí)行另一個任務(wù)珊膜,join方法解決方案
'''
t1 = DownloadThread('沉默的羔羊', 4)
t2 = DownloadThread('恐怖游輪', 5)
t2.start()
t2.join()
t1.start()

競態(tài)條件時數(shù)據(jù)操作的解決方案(鎖)


問題

1.問題
當(dāng)多個線程同時對一個數(shù)據(jù)進(jìn)行讀寫操作,可能會出現(xiàn)一個線程剛把數(shù)據(jù)讀出來還沒來得及寫進(jìn)去宣脉,另外一個線程進(jìn)行讀操作的數(shù)據(jù)安全問題车柠。
2.解決 - 加鎖
1)保證每個數(shù)據(jù)對應(yīng)一個鎖對象
2)操作數(shù)據(jù)前加鎖,數(shù)據(jù)操作完成后釋放鎖

import time
from threading import Thread, Lock

class Account:
    def __init__(self, name, tel, balance=50)
        self.name = name
        self.tel = tel
        self.balance = balance
        # 關(guān)聯(lián)一個鎖對象
        self.lock = Lock()
    def save_money(self, money):
        print("開始存錢")
        # 加鎖
        self.lock.acquire()
        value = self.balance
        time.sleep(4)
        self.balance = value + money
        print("存錢成功:%.2f"%self.balance)
        # 釋放鎖
        self.lock.release()
    def draw_money(self, money):
        print("開始取錢")
        #加鎖
        self.lock.acquire()
        value = self.balance
        if value<money:
            print("取錢失敗竹祷!余額不足")
            return
        self.balance = value - money
        print("取錢成功:%.2f"%self.balance)
        # 釋放鎖
        self.lock.release()
        
account = Account("小H", "13893177183", 10000)

# 一個線程去存錢
t1 = Thread(target=account, save_money, args=(1000,))
# 一個線程去取錢
t2 = Thread(target=account, draw_money, args=(500,))

t1.start()
t2.start()


print("======分隔符======")
# 添加數(shù)據(jù)
share_data = 10000
lock = Lock()

def add_data(value):
    lock.acquire()
    global share_data #保證函數(shù)內(nèi)賦值share_data時谈跛,賦值的是全局變量
    old_data = share_data
    time.sleep(4)
    share_data = old_data + value  #保證函數(shù)內(nèi)賦值share_data時,賦值的是全局變量如果上方未聲明全局變量塑陵,則函數(shù)內(nèi)會創(chuàng)建同名局部變量從而報錯
    lock.release()

t1 = Thread(target=add_data, args=(200,))
t2 = Thread(target=add_data, args=(300,))
t1.start()
t2.start()

t1.join()
t2.join()

print(share_data)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末感憾,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子令花,更是在濱河造成了極大的恐慌阻桅,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,273評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件兼都,死亡現(xiàn)場離奇詭異嫂沉,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)扮碧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,349評論 3 398
  • 文/潘曉璐 我一進(jìn)店門趟章,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人慎王,你說我怎么就攤上這事倡鲸〔鐾啵” “怎么了匆赃?”我有些...
    開封第一講書人閱讀 167,709評論 0 360
  • 文/不壞的土叔 我叫張陵师郑,是天一觀的道長。 經(jīng)常有香客問我漫蛔,道長嗜愈,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,520評論 1 296
  • 正文 為了忘掉前任莽龟,我火速辦了婚禮蠕嫁,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘毯盈。我一直安慰自己剃毒,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 68,515評論 6 397
  • 文/花漫 我一把揭開白布搂赋。 她就那樣靜靜地躺著赘阀,像睡著了一般。 火紅的嫁衣襯著肌膚如雪脑奠。 梳的紋絲不亂的頭發(fā)上基公,一...
    開封第一講書人閱讀 52,158評論 1 308
  • 那天,我揣著相機(jī)與錄音宋欺,去河邊找鬼轰豆。 笑死胰伍,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的酸休。 我是一名探鬼主播骂租,決...
    沈念sama閱讀 40,755評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼斑司!你這毒婦竟也來了渗饮?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,660評論 0 276
  • 序言:老撾萬榮一對情侶失蹤陡厘,失蹤者是張志新(化名)和其女友劉穎抽米,沒想到半個月后特占,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體糙置,經(jīng)...
    沈念sama閱讀 46,203評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,287評論 3 340
  • 正文 我和宋清朗相戀三年是目,在試婚紗的時候發(fā)現(xiàn)自己被綠了谤饭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,427評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡懊纳,死狀恐怖揉抵,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情嗤疯,我是刑警寧澤冤今,帶...
    沈念sama閱讀 36,122評論 5 349
  • 正文 年R本政府宣布,位于F島的核電站茂缚,受9級特大地震影響戏罢,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜脚囊,卻給世界環(huán)境...
    茶點故事閱讀 41,801評論 3 333
  • 文/蒙蒙 一龟糕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧悔耘,春花似錦讲岁、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,272評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至看峻,卻和暖如春郎任,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背备籽。 一陣腳步聲響...
    開封第一講書人閱讀 33,393評論 1 272
  • 我被黑心中介騙來泰國打工舶治, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留分井,地道東北人。 一個月前我還...
    沈念sama閱讀 48,808評論 3 376
  • 正文 我出身青樓霉猛,卻偏偏與公主長得像尺锚,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子惜浅,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,440評論 2 359

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