學(xué)習(xí)筆記day42

每日測(cè)驗(yàn)

  • 簡(jiǎn)述死鎖現(xiàn)象

  • 你用過(guò)哪些隊(duì)列

  • 闡述進(jìn)程池線程池概念及基本使用

  • 什么是協(xié)程,如何簡(jiǎn)單實(shí)現(xiàn)

昨日內(nèi)容回顧

  • 死鎖現(xiàn)象

    """
    即便你知道如何搶鎖釋放鎖 也極有可能造成程序的死鎖現(xiàn)象
    
    后續(xù)我們?cè)趯戫?xiàng)目的時(shí)候 也不會(huì)自己去處理鎖的問(wèn)題 都是底層封裝好的
    所以你不用擔(dān)心
    """
    
  • 遞歸鎖

    """
    它也是一把互斥鎖昌粤,但是它可以被第一個(gè)搶到它的人連續(xù)的acquire和release
    每acquire一次內(nèi)部有一個(gè)引用計(jì)數(shù)加1
    每release一次內(nèi)部有一個(gè)引用計(jì)數(shù)減1
    只要引用計(jì)數(shù)不為0 永遠(yuǎn)也無(wú)法被其他人搶到
    """
    
  • 信號(hào)量

    """
    信號(hào)量在不同的領(lǐng)域和知識(shí)階段可能對(duì)應(yīng)不同的概念
    如果將互斥鎖比喻成一個(gè)廁所 那么信號(hào)量就相當(dāng)于多個(gè)廁所
    """
    
  • event事件

    """
    一些線程/進(jìn)程等待另外一些線程/進(jìn)程發(fā)送可以運(yùn)行的信號(hào) 才開(kāi)始運(yùn)行
    from threading import Event
    e = Event()
    
    # 等待
    e.wait()
    # 發(fā)送信號(hào) 
    e.set()
    """
    
  • 各種隊(duì)列

    """
    1 常見(jiàn)隊(duì)列 queue
      先進(jìn)先出
      q = queue.Queue()
      q.put()
      q.get(timeout=3)
      q.get_nowait()
      q.full()
      q.empty()
    
    2 后進(jìn)先出 LifoQueue()
      q = queue.LifoQueue()
      q.put()
      q.get()
    
    3 優(yōu)先級(jí) PriorityQueue()
      q = queue.PriorityQueue()
      q.put((10,'data'))
      q.put((-5,'data'))
      元祖里面的第一個(gè)參數(shù)是數(shù)字 并且支持負(fù)數(shù)
      數(shù)字越小優(yōu)先級(jí)越高
    """
    
  • 進(jìn)程池線程池

    """
    硬件的發(fā)展肯定是趕不上軟件的開(kāi)發(fā)速度的
      
    思考我們以前借助于開(kāi)設(shè)進(jìn)程和線程的方式來(lái)實(shí)現(xiàn)TCP服務(wù)端的并發(fā)
      每來(lái)一個(gè)客戶端就開(kāi)設(shè)一個(gè)進(jìn)程或者線程
    
    無(wú)論是開(kāi)設(shè)進(jìn)程還是開(kāi)設(shè)線程其實(shí)都需要消耗一定的資源
    
    我們應(yīng)該在保證計(jì)算機(jī)硬件安全的情況下页滚,最大限度的利用計(jì)算機(jī)
    
    池的概念
      它的出現(xiàn)是為了保證計(jì)算機(jī)硬件的安全
      降低了程序的運(yùn)行效率 但是保證了計(jì)算機(jī)硬件安全
    """
    # 進(jìn)程池線程池都不需要我們自己去造 直接使用封裝好的模塊
    from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
    # 1 生成進(jìn)程池線程池
    pool1 = ThreadPoolExecutor()  # 不填默認(rèn)是cpu個(gè)數(shù)的五倍
    pool2 = ProcessPoolExecutor()  # 不填默認(rèn)就是cpu的個(gè)數(shù)
    
    # 2 朝池子中提交任務(wù)
    pool1.submit(task,args...)  # 異步提交
    
    # 3 submit其實(shí)會(huì)返回一個(gè)Future類的對(duì)象 該對(duì)象調(diào)用result就能獲取到任務(wù)的結(jié)果
    res = pool1.submit(task,args...) 
    res.result()  # 同步
    
    # 4 池子對(duì)象的方法
    pool1.shotdown()  # 關(guān)閉池子 等待池子中所有的任務(wù)運(yùn)行結(jié)束 再繼續(xù)往后執(zhí)行代碼
    
    # 5 異步回調(diào)機(jī)制
    """給每一個(gè)異步提交的任務(wù)綁定一個(gè)方法萤彩,一旦任務(wù)有結(jié)果了會(huì)立刻自動(dòng)觸發(fā)該方法"""
    pool1.submit(task,args).add_done_callback(call_back)
    # 注意異步回調(diào)函數(shù)拿到的也是一個(gè)對(duì)象 
    
  • 協(xié)程

    """
    單線程下實(shí)現(xiàn)并發(fā)
    這個(gè)概念完全是我們程序員自己想出來(lái)
    
    多道技術(shù)
      切換+保存狀態(tài)
    
    我們想通過(guò)代碼層面自己檢測(cè)IO行為村视。一旦遇到IO代碼層面實(shí)現(xiàn)切換
    這樣給操作系統(tǒng)的感覺(jué)好像我這個(gè)程序一直運(yùn)行沒(méi)有IO
    欺騙操作系統(tǒng)從而最大化的利用CPU
    
    一味的切換加保存狀態(tài)也有可能會(huì)降低程序的效率
    計(jì)算密集型的  不行
    IO密集型的    可以
    """
    
  • gevent模塊

    # 該模塊能夠幫我們檢測(cè)IO并實(shí)現(xiàn)切換
    from gevent import monkey;monkey.patch_all()
    from gevent import spawn
    
    # spawn在檢測(cè)的時(shí)候 是異步提交的
    spawn(server).join()
    g = spawn(server)
    g.join
    
  • 基于協(xié)程實(shí)現(xiàn)TCP服務(wù)端單線程下的并發(fā)

    # 代碼稍微摟一眼 感受它的牛逼之處
    

總結(jié)

"""
多進(jìn)程下面開(kāi)設(shè)多線程
多線程下面再利用協(xié)程
最大長(zhǎng)度的提升軟件運(yùn)行的效率
"""

今日內(nèi)容概要

  • IO模型

  • 復(fù)習(xí)網(wǎng)絡(luò)和并發(fā)知識(shí)點(diǎn)

  • 后期課程安排

IO模型簡(jiǎn)介

"""
我們這里研究的IO模型都是針對(duì)網(wǎng)絡(luò)IO的
Stevens在文章中一共比較了五種IO Model:
    * blocking IO           阻塞IO
    * nonblocking IO      非阻塞IO
    * IO multiplexing      IO多路復(fù)用
    * signal driven IO     信號(hào)驅(qū)動(dòng)IO
    * asynchronous IO    異步IO
    由signal driven IO(信號(hào)驅(qū)動(dòng)IO)在實(shí)際中并不常用伊磺,所以主要介紹其余四種IO Model盛正。
"""
#1)等待數(shù)據(jù)準(zhǔn)備 (Waiting for the data to be ready)
#2)將數(shù)據(jù)從內(nèi)核拷貝到進(jìn)程中(Copying the data from the kernel to the process)

同步異步
阻塞非阻塞
常見(jiàn)的網(wǎng)絡(luò)阻塞狀態(tài):
    accept
    recv
    recvfrom
    
    send雖然它也有io行為 但是不在我們的考慮范圍

阻塞IO模型

"""
我們之前寫的都是阻塞IO模型  協(xié)程除外
"""
import socket


server = socket.socket()
server.bind(('127.0.0.1',8080))
server.listen(5)


while True:
    conn, addr = server.accept()
    while True:
        try:
            data = conn.recv(1024)
            if len(data) == 0:break
            print(data)
            conn.send(data.upper())
        except ConnectionResetError as e:
            break
    conn.close()
    
# 在服務(wù)端開(kāi)設(shè)多進(jìn)程或者多線程 進(jìn)程池線程池 其實(shí)還是沒(méi)有解決IO問(wèn)題    
該等的地方還是得等 沒(méi)有規(guī)避
只不過(guò)多個(gè)人等待的彼此互不干擾

非阻塞IO

"""
要自己實(shí)現(xiàn)一個(gè)非阻塞IO模型
"""
import socket
import time


server = socket.socket()
server.bind(('127.0.0.1', 8081))
server.listen(5)
server.setblocking(False)
# 將所有的網(wǎng)絡(luò)阻塞變?yōu)榉亲枞?r_list = []
del_list = []
while True:
    try:
        conn, addr = server.accept()
        r_list.append(conn)
    except BlockingIOError:
        # time.sleep(0.1)
        # print('列表的長(zhǎng)度:',len(r_list))
        # print('做其他事')
        for conn in r_list:
            try:
                data = conn.recv(1024)  # 沒(méi)有消息 報(bào)錯(cuò)
                if len(data) == 0:  # 客戶端斷開(kāi)鏈接
                    conn.close()  # 關(guān)閉conn
                    # 將無(wú)用的conn從r_list刪除
                    del_list.append(conn)
                    continue
                conn.send(data.upper())
            except BlockingIOError:
                continue
            except ConnectionResetError:
                conn.close()
                del_list.append(conn)
        # 揮手無(wú)用的鏈接
        for conn in del_list:
            r_list.remove(conn)
        del_list.clear()

# 客戶端
import socket


client = socket.socket()
client.connect(('127.0.0.1',8081))


while True:
    client.send(b'hello world')
    data = client.recv(1024)
    print(data)

總結(jié)

"""
雖然非阻塞IO給你的感覺(jué)非常的牛逼
但是該模型會(huì)  長(zhǎng)時(shí)間占用著CPU并且不干活 讓CPU不停的空轉(zhuǎn)
我們實(shí)際應(yīng)用中也不會(huì)考慮使用非阻塞IO模型

任何的技術(shù)點(diǎn)都有它存在的意義 
實(shí)際應(yīng)用或者是思想借鑒
"""

IO多路復(fù)用

"""
當(dāng)監(jiān)管的對(duì)象只有一個(gè)的時(shí)候 其實(shí)IO多路復(fù)用連阻塞IO都比比不上!P悸瘛豪筝!
但是IO多路復(fù)用可以一次性監(jiān)管很多個(gè)對(duì)象

server = socket.socket()
conn,addr = server.accept()

監(jiān)管機(jī)制是操作系統(tǒng)本身就有的 如果你想要用該監(jiān)管機(jī)制(select)
需要你導(dǎo)入對(duì)應(yīng)的select模塊
"""
import socket
import select


server = socket.socket()
server.bind(('127.0.0.1',8080))
server.listen(5)
server.setblocking(False)
read_list = [server]


while True:
    r_list, w_list, x_list = select.select(read_list, [], [])
    """
    幫你監(jiān)管
    一旦有人來(lái)了 立刻給你返回對(duì)應(yīng)的監(jiān)管對(duì)象
    """
    # print(res)  # ([<socket.socket fd=3, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=0, laddr=('127.0.0.1', 8080)>], [], [])
    # print(server)
    # print(r_list)
    for i in r_list:  #
        """針對(duì)不同的對(duì)象做不同的處理"""
        if i is server:
            conn, addr = i.accept()
            # 也應(yīng)該添加到監(jiān)管的隊(duì)列中
            read_list.append(conn)
        else:
            res = i.recv(1024)
            if len(res) == 0:
                i.close()
                # 將無(wú)效的監(jiān)管對(duì)象 移除
                read_list.remove(i)
                continue
            print(res)
            i.send(b'heiheiheiheihei')

 # 客戶端
import socket


client = socket.socket()
client.connect(('127.0.0.1',8080))


while True:

    client.send(b'hello world')
    data = client.recv(1024)
    print(data)

總結(jié)

"""
監(jiān)管機(jī)制其實(shí)有很多
select機(jī)制  windows linux都有

poll機(jī)制    只在linux有   poll和select都可以監(jiān)管多個(gè)對(duì)象 但是poll監(jiān)管的數(shù)量更多

上述select和poll機(jī)制其實(shí)都不是很完美 當(dāng)監(jiān)管的對(duì)象特別多的時(shí)候
可能會(huì)出現(xiàn) 極其大的延時(shí)響應(yīng)

epoll機(jī)制   只在linux有
    它給每一個(gè)監(jiān)管對(duì)象都綁定一個(gè)回調(diào)機(jī)制
    一旦有響應(yīng) 回調(diào)機(jī)制立刻發(fā)起提醒

針對(duì)不同的操作系統(tǒng)還需要考慮不同檢測(cè)機(jī)制 書寫代碼太多繁瑣
有一個(gè)人能夠根據(jù)你跑的平臺(tái)的不同自動(dòng)幫你選擇對(duì)應(yīng)的監(jiān)管機(jī)制
selectors模塊
"""

異步IO

"""
異步IO模型是所有模型中效率最高的 也是使用最廣泛的
相關(guān)的模塊和框架
    模塊:asyncio模塊
    異步框架:sanic tronado twisted
        速度快!H副恕壤蚜!
"""
import threading
import asyncio


@asyncio.coroutine
def hello():
    print('hello world %s'%threading.current_thread())
    yield from asyncio.sleep(1)  # 換成真正的IO操作
    print('hello world %s' % threading.current_thread())


loop = asyncio.get_event_loop()
tasks = [hello(),hello()]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()

四個(gè)IO模型對(duì)比

參考博客園圖解即寡,稍微了解即可

網(wǎng)絡(luò)并發(fā)知識(shí)點(diǎn)梳理

  • 軟件開(kāi)發(fā)架構(gòu)

  • 互聯(lián)網(wǎng)協(xié)議

    """
    osi七層
    五層
    每一層都是干嘛的
      以太網(wǎng)協(xié)議  廣播風(fēng)暴
      IP協(xié)議
      
      TCP/UDP
    """
    
  • 三次握手四次揮手

  • socket簡(jiǎn)介

  • TCP黏包問(wèn)題 定制固定長(zhǎng)度的報(bào)頭

  • UDP協(xié)議

  • socketserver模塊

  • 操作系統(tǒng)發(fā)展史
  • 多道技術(shù)
  • 進(jìn)程理論
  • 開(kāi)啟進(jìn)程的兩種方式
  • 互斥鎖
  • 生產(chǎn)者消費(fèi)者模型
  • 線程理論
  • 開(kāi)啟線程的兩種方式
  • GIL全局解釋器鎖
  • 進(jìn)程池線程池
  • 協(xié)程的概念
  • IO模型的了解
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末徊哑,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子聪富,更是在濱河造成了極大的恐慌莺丑,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,110評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異梢莽,居然都是意外死亡萧豆,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,443評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門昏名,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)涮雷,“玉大人,你說(shuō)我怎么就攤上這事轻局『檠迹” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 165,474評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵仑扑,是天一觀的道長(zhǎng)览爵。 經(jīng)常有香客問(wèn)我,道長(zhǎng)镇饮,這世上最難降的妖魔是什么蜓竹? 我笑而不...
    開(kāi)封第一講書人閱讀 58,881評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮储藐,結(jié)果婚禮上俱济,老公的妹妹穿的比我還像新娘。我一直安慰自己邑茄,他們只是感情好姨蝴,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,902評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著肺缕,像睡著了一般左医。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上同木,一...
    開(kāi)封第一講書人閱讀 51,698評(píng)論 1 305
  • 那天浮梢,我揣著相機(jī)與錄音,去河邊找鬼彤路。 笑死秕硝,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的洲尊。 我是一名探鬼主播远豺,決...
    沈念sama閱讀 40,418評(píng)論 3 419
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼坞嘀!你這毒婦竟也來(lái)了躯护?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,332評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤丽涩,失蹤者是張志新(化名)和其女友劉穎棺滞,沒(méi)想到半個(gè)月后裁蚁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,796評(píng)論 1 316
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡继准,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,968評(píng)論 3 337
  • 正文 我和宋清朗相戀三年枉证,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片移必。...
    茶點(diǎn)故事閱讀 40,110評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡室谚,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出崔泵,到底是詐尸還是另有隱情舞萄,我是刑警寧澤管削,帶...
    沈念sama閱讀 35,792評(píng)論 5 346
  • 正文 年R本政府宣布倒脓,位于F島的核電站,受9級(jí)特大地震影響含思,放射性物質(zhì)發(fā)生泄漏崎弃。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,455評(píng)論 3 331
  • 文/蒙蒙 一含潘、第九天 我趴在偏房一處隱蔽的房頂上張望饲做。 院中可真熱鬧,春花似錦遏弱、人聲如沸盆均。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,003評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)泪姨。三九已至,卻和暖如春饰抒,著一層夾襖步出監(jiān)牢的瞬間肮砾,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,130評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工袋坑, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留仗处,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,348評(píng)論 3 373
  • 正文 我出身青樓枣宫,卻偏偏與公主長(zhǎng)得像婆誓,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子也颤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,047評(píng)論 2 355

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