每日測(cè)驗(yàn)
- 闡述同步異步阻塞非阻塞概念
- 手寫開啟進(jìn)程的兩種方式
昨日內(nèi)容回顧
如何復(fù)習(xí)知識(shí)點(diǎn):總分總
先列出提綱派殷,再依次復(fù)習(xí)村生,最后再總結(jié)一下
-
操作系統(tǒng)的發(fā)展史
""" 其實(shí)主要就是圍繞cpu的利用率問(wèn)題 """
-
多道技術(shù)
""" 單核實(shí)現(xiàn)并發(fā)的效果 并發(fā):看起來(lái)像同時(shí)運(yùn)行的就可以叫做并發(fā) 并行:真正意義上的同時(shí)運(yùn)行 ps:明顯出軌 >>>: 星軌 空間與時(shí)間上的復(fù)用 空間上 多個(gè)程序公用一套計(jì)算機(jī)硬件 時(shí)間上 切換+保存狀態(tài) """ # 切換分為兩種 # 1.當(dāng)一個(gè)程序遇到IO操作,操作系統(tǒng)會(huì)立刻剝奪該程序的cpu執(zhí)行權(quán)限(提供了cpu利用率并且不影響程序的執(zhí)行效率) # 2.當(dāng)一個(gè)程序長(zhǎng)時(shí)間占用cpu洒宝,操作系統(tǒng)也會(huì)立刻剝奪該程序的cpu執(zhí)行權(quán)限(降低了程序的運(yùn)行效率但是玩出了并發(fā)的效果)
-
進(jìn)程
""" 程序就是一堆死代碼 死 進(jìn)程則是正在執(zhí)行的過(guò)程 活 """ # 進(jìn)程的調(diào)度算法 """ 先來(lái)先服務(wù)調(diào)度算法 短作業(yè)優(yōu)先調(diào)度算法 時(shí)間片輪轉(zhuǎn)法+多級(jí)反饋隊(duì)列 """
-
進(jìn)程運(yùn)行的三狀態(tài)圖
""" 就緒態(tài):一切程序必須要先過(guò)就緒態(tài)才能加入運(yùn)行態(tài) 運(yùn)行態(tài):正在被cpu執(zhí)行 阻塞態(tài):程序遇到IO操作了 理想:我們希望我開發(fā)的程序一致處于就緒態(tài)與運(yùn)行態(tài)之間 """
-
兩對(duì)重要概念
-
同步與異步
"""任務(wù)的提交方式""" 同步 任務(wù)提交之后原地等待任務(wù)的返回結(jié)果期間不做任何事情 異步 任務(wù)提交之后不原地等待任務(wù)的返回結(jié)果執(zhí)行執(zhí)行下一行代碼 結(jié)果由異步回調(diào)機(jī)制做處理
-
阻塞非阻塞
"""程序的運(yùn)行狀態(tài)""" 阻塞:阻塞態(tài) 非阻塞:就緒態(tài) 運(yùn)行態(tài)
上面的兩對(duì)概念通常會(huì)組合出現(xiàn)蝇闭,但是最常用的就是異步非阻塞
-
-
開啟進(jìn)程的兩種方式
""" from mutiprocessing import Process # 1 類實(shí)例化產(chǎn)生對(duì)象 # 2 類的繼承 run方法 再windows里面開啟進(jìn)程的代碼一定要寫在main代碼塊內(nèi) 創(chuàng)建一個(gè)進(jìn)程就是在內(nèi)存空間中申請(qǐng)一塊內(nèi)存空間將需要的代碼丟進(jìn)去 """
-
join方法
""" 主進(jìn)程等待子進(jìn)程代碼運(yùn)行完畢后再往下執(zhí)行代碼 """
-
進(jìn)程間數(shù)據(jù)是相互隔離的(默認(rèn)情況下)
ps:人工智能相關(guān)參考網(wǎng)站
https://www.xfyun.cn/?ch=bd05&b_scene_zt=1
http://ai.baidu.com/creation/main/demo
作為一名python程序員當(dāng)你遇到一個(gè)功能的時(shí)候罕偎,第一時(shí)間你可以考慮是否有對(duì)應(yīng)的模塊已經(jīng)幫你實(shí)現(xiàn)了該功能
今日內(nèi)容概要
- 進(jìn)程對(duì)象及其他方法
- 僵尸進(jìn)程與孤兒進(jìn)程
- 守護(hù)進(jìn)程
- 互斥鎖
- 隊(duì)列介紹
- 進(jìn)程間通信IPC機(jī)制
- 生產(chǎn)者消費(fèi)者模型
- 線程相關(guān)知識(shí)點(diǎn)
今日內(nèi)容詳細(xì)
如果你的pycharm老是過(guò)期溜在,你可以直接下載最新版本的pycharm陌知,然后加入一個(gè)網(wǎng)站獲取激活碼即可
http://idea.medeming.com/jets/
進(jìn)程對(duì)象及其他方法
"""
一臺(tái)計(jì)算機(jī)上面運(yùn)行著很多進(jìn)程,那么計(jì)算機(jī)是如何區(qū)分并管理這些進(jìn)程服務(wù)端的呢掖肋?
計(jì)算機(jī)會(huì)給每一個(gè)運(yùn)行的進(jìn)程分配一個(gè)PID號(hào)
如何查看
windows電腦
進(jìn)入cmd輸入tasklist即可查看
tasklist |findstr PID查看具體的進(jìn)程
mac電腦
進(jìn)入終端之后輸入ps aux
ps aux|grep PID查看具體的進(jìn)程
"""
from multiprocessing import Process, current_process
current_process().pid # 查看當(dāng)前進(jìn)程的進(jìn)程號(hào)
import os
os.getpid() # 查看當(dāng)前進(jìn)程進(jìn)程號(hào)
os.getppid() # 查看當(dāng)前進(jìn)程的父進(jìn)程進(jìn)程號(hào)
p.terminate() # 殺死當(dāng)前進(jìn)程
# 是告訴操作系統(tǒng)幫你去殺死當(dāng)前進(jìn)程 但是需要一定的時(shí)間 而代碼的運(yùn)行速度極快
time.sleep(0.1)
print(p.is_alive()) # 判斷當(dāng)前進(jìn)程是否存活
僵尸進(jìn)程與孤兒進(jìn)程(了解)
# 僵尸進(jìn)程
"""
死了但是沒(méi)有死透
當(dāng)你開設(shè)了子進(jìn)程之后 該進(jìn)程死后不會(huì)立刻釋放占用的進(jìn)程號(hào)
因?yàn)槲乙尭高M(jìn)程能夠查看到它開設(shè)的子進(jìn)程的一些基本信息 占用的pid號(hào) 運(yùn)行時(shí)間仆葡。。志笼。
所有的進(jìn)程都會(huì)步入僵尸進(jìn)程
父進(jìn)程不死并且在無(wú)限制的創(chuàng)建子進(jìn)程并且子進(jìn)程也不結(jié)束
回收子進(jìn)程占用的pid號(hào)
父進(jìn)程等待子進(jìn)程運(yùn)行結(jié)束
父進(jìn)程調(diào)用join方法
"""
# 孤兒進(jìn)程
"""
子進(jìn)程存活沿盅,父進(jìn)程意外死亡
操作系統(tǒng)會(huì)開設(shè)一個(gè)“兒童福利院”專門管理孤兒進(jìn)程回收相關(guān)資源
"""
守護(hù)進(jìn)程
from multiprocessing import Process
import time
def task(name):
print('%s總管正在活著'% name)
time.sleep(3)
print('%s總管正在死亡' % name)
if __name__ == '__main__':
p = Process(target=task,args=('egon',))
# p = Process(target=task,kwargs={'name':'egon'})
p.daemon = True # 將進(jìn)程p設(shè)置成守護(hù)進(jìn)程 這一句一定要放在start方法上面才有效否則會(huì)直接報(bào)錯(cuò)
p.start()
print('皇帝jason壽終正寢')
互斥鎖
多個(gè)進(jìn)程操作同一份數(shù)據(jù)的時(shí)候,會(huì)出現(xiàn)數(shù)據(jù)錯(cuò)亂的問(wèn)題
針對(duì)上述問(wèn)題纫溃,解決方式就是加鎖處理:將并發(fā)變成串行腰涧,犧牲效率但是保證了數(shù)據(jù)的安全
from multiprocessing import Process, Lock
import json
import time
import random
# 查票
def search(i):
# 文件操作讀取票數(shù)
with open('data','r',encoding='utf8') as f:
dic = json.load(f)
print('用戶%s查詢余票:%s'%(i, dic.get('ticket_num')))
# 字典取值不要用[]的形式 推薦使用get 你寫的代碼打死都不能報(bào)錯(cuò)!N珊啤窖铡!
# 買票 1.先查 2.再買
def buy(i):
# 先查票
with open('data','r',encoding='utf8') as f:
dic = json.load(f)
# 模擬網(wǎng)絡(luò)延遲
time.sleep(random.randint(1,3))
# 判斷當(dāng)前是否有票
if dic.get('ticket_num') > 0:
# 修改數(shù)據(jù)庫(kù) 買票
dic['ticket_num'] -= 1
# 寫入數(shù)據(jù)庫(kù)
with open('data','w',encoding='utf8') as f:
json.dump(dic,f)
print('用戶%s買票成功'%i)
else:
print('用戶%s買票失敗'%i)
# 整合上面兩個(gè)函數(shù)
def run(i, mutex):
search(i)
# 給買票環(huán)節(jié)加鎖處理
# 搶鎖
mutex.acquire()
buy(i)
# 釋放鎖
mutex.release()
if __name__ == '__main__':
# 在主進(jìn)程中生成一把鎖 讓所有的子進(jìn)程搶 誰(shuí)先搶到誰(shuí)先買票
mutex = Lock()
for i in range(1,11):
p = Process(target=run, args=(i, mutex))
p.start()
"""
擴(kuò)展 行鎖 表鎖
注意:
1.鎖不要輕易的使用疗锐,容易造成死鎖現(xiàn)象(我們寫代碼一般不會(huì)用到,都是內(nèi)部封裝好的)
2.鎖只在處理數(shù)據(jù)的部分加來(lái)保證數(shù)據(jù)安全(只在爭(zhēng)搶數(shù)據(jù)的環(huán)節(jié)加鎖處理即可)
"""
進(jìn)程間通信
隊(duì)列Queue模塊
"""
管道:subprocess
stdin stdout stderr
隊(duì)列:管道+鎖
隊(duì)列:先進(jìn)先出
堆棧:先進(jìn)后出
"""
from multiprocessing import Queue
# 創(chuàng)建一個(gè)隊(duì)列
q = Queue(5) # 括號(hào)內(nèi)可以傳數(shù)字 標(biāo)示生成的隊(duì)列最大可以同時(shí)存放的數(shù)據(jù)量
# 往隊(duì)列中存數(shù)據(jù)
q.put(111)
q.put(222)
q.put(333)
# print(q.full()) # 判斷當(dāng)前隊(duì)列是否滿了
# print(q.empty()) # 判斷當(dāng)前隊(duì)列是否空了
q.put(444)
q.put(555)
# print(q.full()) # 判斷當(dāng)前隊(duì)列是否滿了
# q.put(666) # 當(dāng)隊(duì)列數(shù)據(jù)放滿了之后 如果還有數(shù)據(jù)要放程序會(huì)阻塞 直到有位置讓出來(lái) 不會(huì)報(bào)錯(cuò)
"""
存取數(shù)據(jù) 存是為了更好的取
千方百計(jì)的存万伤、簡(jiǎn)單快捷的取
同在一個(gè)屋檐下
差距為何那么大
"""
# 去隊(duì)列中取數(shù)據(jù)
v1 = q.get()
v2 = q.get()
v3 = q.get()
v4 = q.get()
v5 = q.get()
# print(q.empty())
# V6 = q.get_nowait() # 沒(méi)有數(shù)據(jù)直接報(bào)錯(cuò)queue.Empty
# v6 = q.get(timeout=3) # 沒(méi)有數(shù)據(jù)之后原地等待三秒之后再報(bào)錯(cuò) queue.Empty
try:
v6 = q.get(timeout=3)
print(v6)
except Exception as e:
print('一滴都沒(méi)有了!')
# # v6 = q.get() # 隊(duì)列中如果已經(jīng)沒(méi)有數(shù)據(jù)的話 get方法會(huì)原地阻塞
# print(v1, v2, v3, v4, v5, v6)
"""
q.full()
q.empty()
q.get_nowait()
在多進(jìn)程的情況下是不精確
"""
IPC機(jī)制
from multiprocessing import Queue, Process
"""
研究思路
1.主進(jìn)程跟子進(jìn)程借助于隊(duì)列通信
2.子進(jìn)程跟子進(jìn)程借助于隊(duì)列通信
"""
def producer(q):
q.put('我是23號(hào)技師 很高興為您服務(wù)')
def consumer(q):
print(q.get())
if __name__ == '__main__':
q = Queue()
p = Process(target=producer,args=(q,))
p1 = Process(target=consumer,args=(q,))
p.start()
p1.start()
生產(chǎn)者消費(fèi)者模型
"""
生產(chǎn)者:生產(chǎn)/制造東西的
消費(fèi)者:消費(fèi)/處理東西的
該模型除了上述兩個(gè)之外還需要一個(gè)媒介
生活中的例子做包子的將包子做好后放在蒸籠(媒介)里面窒悔,買包子的取蒸籠里面拿
廚師做菜做完之后用盤子裝著給你消費(fèi)者端過(guò)去
生產(chǎn)者和消費(fèi)者之間不是直接做交互的,而是借助于媒介做交互
生產(chǎn)者(做包子的) + 消息隊(duì)列(蒸籠) + 消費(fèi)者(吃包子的)
"""
線程理論
致命三問(wèn)
-
什么是線程
""" 進(jìn)程:資源單位 線程:執(zhí)行單位 將操作系統(tǒng)比喻成一個(gè)大的工廠 那么進(jìn)程就相當(dāng)于工廠里面的車間 而線程就是車間里面的流水線 每一個(gè)進(jìn)程肯定自帶一個(gè)線程 再次總結(jié): 進(jìn)程:資源單位(起一個(gè)進(jìn)程僅僅只是在內(nèi)存空間中開辟一塊獨(dú)立的空間) 線程:執(zhí)行單位(真正被cpu執(zhí)行的其實(shí)是進(jìn)程里面的線程敌买,線程指的就是代碼的執(zhí)行過(guò)程简珠,執(zhí)行代碼中所需要使用到的資源都找所在的進(jìn)程索要) 進(jìn)程和線程都是虛擬單位,只是為了我們更加方便的描述問(wèn)題 """
-
為何要有線程
""" 開設(shè)進(jìn)程 1.申請(qǐng)內(nèi)存空間 耗資源 2.“拷貝代碼” 耗資源 開線程 一個(gè)進(jìn)程內(nèi)可以開設(shè)多個(gè)線程虹钮,在用一個(gè)進(jìn)程內(nèi)開設(shè)多個(gè)線程無(wú)需再次申請(qǐng)內(nèi)存空間操作 總結(jié): 開設(shè)線程的開銷要遠(yuǎn)遠(yuǎn)的小于進(jìn)程的開銷 同一個(gè)進(jìn)程下的多個(gè)線程數(shù)據(jù)是共享的!!! """ 我們要開發(fā)一款文本編輯器 獲取用戶輸入的功能 實(shí)時(shí)展示到屏幕的功能 自動(dòng)保存到硬盤的功能 針對(duì)上面這三個(gè)功能聋庵,開設(shè)進(jìn)程還是線程合適?芙粱?祭玉? 開三個(gè)線程處理上面的三個(gè)功能更加的合理
如何使用
今日作業(yè)
-
整理今日內(nèi)容到博客
描述知識(shí)點(diǎn)一定要用自己的話術(shù)概括,不要死記硬背4号稀M鸦酢!
把知識(shí)點(diǎn)理解了律姨,再去用自己語(yǔ)言組織說(shuō)出來(lái)即可
手動(dòng)書寫生產(chǎn)者消費(fèi)者代碼
思考:如何實(shí)現(xiàn)TCP服務(wù)端并發(fā)的效果