并发编程-单元练习题
1、簡述計算機操作系統中的“中斷”的作用?
中斷是指在計算機執行期間,系統內發生任何非尋常的或非預期的急需處理事件,使得cpu暫時中斷當前正在執行的程序, 轉去執行相應的事件處理程序。待處理完畢后又返回原來被中斷處繼續執行或調度新的進程執行的過程。 它使計算機可以更好更快利用有限的系統資源解決系統響應速度和運行效率的一種控制技術。實時響應,系統調度。
2、簡述計算機內存中的“內核態”和“用戶態”;
內核態:cpu可以訪問內存的所有數據,包括外圍設備,例如硬盤,網卡,cpu也可以將自己從一個程序切換到另一個程序。 用戶態:只能受限的訪問內存,且不允許訪問外圍設備,占用cpu的能力被剝奪,cpu資源可以被其他程序獲取。 為什么要有用戶態和內核態?由于需要限制不同的程序之間的訪問能力,防止他們獲取別的程序的內存數據,或者獲取外圍設備的數據,并發送到網絡,cpu劃分出兩個權限等級:用戶態和內核態。3、什么是進程、線程、協程、多線程和多進程、線程池和進程池
進程: 正在進行的一個過程或者說一個任務,負責執行任務的是cpu,進程用來把資源集中到一起,進程是資源單位,或者說是資源集合 線程: 線程是cpu的執行單位 多線程和多進程的區別: 0、創建進程的開銷遠大于創建線程的開銷。 1、開啟速度 在主進程下開啟線程比 開啟子進程快 (線程:線程先執行,在執行進程程序) 2、pid 對比:在主進程下開啟多個線程(進程和線程pid相同);在主進程下開啟子進程(pid不相同) 3、同一進程內的線程共享該進程的數據(進程之間的地址是隔離的;同一進程內的線程共享該進程的地址空間)協程: 協程:是單線程下的并發,又稱微線程,纖程。 協程是一種用戶態的輕量級線程,即協程是由用戶程序自己控制調度的。 優點如下: 1. 協程的切換開銷更小,屬于程序級別的切換,操作系統完全感知不到,因而更加輕量級 2. 單線程內就可以實現并發的效果,最大限度地利用cpu 缺點如下: 1. 協程的本質是單線程下,無法利用多核,可以是一個程序開啟多個進程,每個進程內開啟多個線程,每個線程內開啟協程 2. 協程指的是單個線程,因而一旦協程出現阻塞,將會阻塞整個線程進程池與線程池作用: # 為什么建池 :我們必須對服務器開啟的進程數或者線程數加以控制,讓機器在一個自己可以承受的范圍內運行 # 這就是進程池或線程池的作用協程與線程的區別:
協程:單線程下的并發。協程是一種用戶態的輕量級線程,即協程是由用戶程序自己控制調度的。
1.python的線程是屬于內核級別的,即由操作系統控制調度(如單線程遇到io或執行時間過長就會被迫交出cpu執行權限,切換其他的線程運行)
2.單線程內開啟協程,一旦遇到io,就會從應用程序級別(而非操作系統)控制切換,以此來提升效率(!!非io操作的切換與效率無關)
4、請簡述你對join、daemon方法的理解,舉出它們在生產環境中的使用場景;
join: 等待一個任務執行完畢;可以將并發變成串行。 daemon: 守護進程(守護線程)會等待主進程(主線程)運行完畢后被銷毀。運行完畢:1.對主進程來說,運行完畢指的是主進程代碼運行完畢。2.對主線程來說,運行完畢指的是主線程所在的進程內所有非守護線程統統運行完畢,主線程才算運行完畢。4、threading中Lock和RLock的相同點和不同點;
Lock():互斥鎖,只能被acquire一次,可能會發生死鎖情況。 RLock():遞歸鎖,可以連續acquire多次。 RLock = Lock + countercounter:記錄了acquire的次數,直到一個線程所有的acquire都被release,其他線程才能獲得資源。?
3、進程間通信方式有哪些?
進程指:正在執行的一個程序或者說一個任務,負責執行任務的是cpu。進程是用來把資源集中到一起的,進程是資源單位,或者說資源集合。進程間通信(IPC) 消息隊列(??? 隊列?=?管道?+?鎖) 管道(使用消息傳遞的) 有名管道(FIFO) 信號量 共享內存 套接字(socket)
4、簡述你對管道、隊列的理解;
管道通常指無名管道 1、它是半雙工的(即數據只能在一個方向上流動),具有固定的讀端和寫端 2、它只能用于具有親緣關系的進程中通信(也就是父與子進程或者兄弟進程之間) 3、數據不可反復讀取了,即讀了之后歡喜紅區中就沒有了 消息隊列 1、消息隊列是面向記錄的,其中的消息具有特定的格式以及特定的優先級 2、消息隊列獨立于發送與接收進程。進程終止時,消息隊列及其內容不會被刪除。 3、消息隊列可以實現消息隨機查詢。隊列 = 管道 + 鎖5、請列舉你知道的進程間通信方式;
隊列,信號量(Semaphore),Event事件,定時器Timer,線程queue,進程池和線程池,異步調用+回調機制6、什么是同步I/O,什么是異步I/O?
同步I/O操作:實際的I/O操作將導致請求進程阻塞,直到I/O操作完成。
異步I/O操作:實際的I/O操作不導致請求進程阻塞。
?
同步或者異步I/O主要是指訪問數據的機制(即實際I/O操作的完成方式),
同步?一般指主動請求并等待I/O操作完畢的方式,I/O操作未完成前,會導致應用進程掛起;
而異步 指用戶進程觸發IO操作以后便開始做自己的事情,而當IO操作已經完成的時候會得到IO
完成的通知(異步的特點就是通知),這可以使進程在數據讀寫時也不阻塞。
?
7、請問multiprocessing模塊中的Value、Array類的作用是什么?舉例說明它們的使用場景
python 多進程通信Queue Pipe Value Array queue和pipe用來在進程間傳遞消息; Value + Array 是python中共享內存映射文件的方法;速度比較快.8、請問multiprocessing模塊中的Manager類的作用是什么?與Value和Array類相比,Manager的優缺點是什么?
Python multiprocessing.Manager(進程間共享數據) Python中進程間共享數據,除了基本的queue,pipe和value+array外,還提供了更高層次的封裝。使用multiprocessing.Manager可以簡單地使用這些高級接口。 Manager支持的類型有list,dict,Namespace,Lock,RLock,Semaphore,BoundedSemaphore,Condition,Event,Queue,Value和Array。?編程題
1、請寫一個包含10個線程的程序,主線程必須等待每一個子線程執行完成之后才結束執行,每一個子線程執行的時候都需要打印當前線程名、當前活躍線程數量;
from threading import Thread,currentThread,activeCount import time def task(n):print('線程名:%s----%s'%(currentThread().name,n))time.sleep(1)print('數量:%s'%activeCount())if __name__ == "__main__":t_li = []for i in range(10):t = Thread(target=task,args=(i,))t.start()t_li.append(t)for t in t_li:t.join()print('主,end----')2、請寫一個包含10個線程的程序,并給每一個子線程都創建名為"name"的線程私有變量,變量值為“Alex”;
from threading import Thread def task(name):print( name,'is running') if __name__ == '__main__':for i in range(10):name = f"alex{i}"t=Thread(target=task,args=(name,))t.start()print('主 end')3、請使用協程寫一個消費者生產者模型;
import gevent from gevent import monkey;monkey.patch_all() def consumer(i):print('消費',i) def producter(i):print('生產',i)if __name__ == '__main__':for i in range(10):g1 = gevent.spawn(producter,i)g2 = gevent.spawn(consumer,i)g1.join()g2.join()-------------------------------------------
# 方法二、
def consumer():
while True:
x=yield
print('消費',x)
def producter():
c=consumer()
next(c)
for i in range(10):
print('生產',i)
c.send(i)
producter() ?
4、寫一個程序,包含十個線程,子線程必須等待主線程sleep 10秒鐘之后才執行,并打印當前時間;
from threading import Thread,Event,currentThread import time,datetimedef task():print(f"{currentThread().getName()} 等待")event.wait()print(f"{currentThread().getName()},{datetime.datetime.now()} is running") if __name__ == '__main__':event=Event()for i in range(10):t=Thread(target=task)t.start()time.sleep(10)event.set()---------------------------------------------------------------------------------
from threading import Event
event.isSet():返回event的狀態值;
event.wait():如果 event.isSet()==False將阻塞線程;
event.set(): 設置event的狀態值為True,所有阻塞池的線程激活進入就緒狀態, 等待操作系統調度;
event.clear():恢復event的狀態值為False。
5、寫一個程序,包含十個線程,同時只能有五個子線程并行執行;
方法二、用信號量的方法(Semaphore)
from threading import Thread, Semaphore, currentThread import timedef task():sm.acquire()print(currentThread().getName())time.sleep(2)sm.release()if __name__ == '__main__':sm = Semaphore(5)start = time.time()for i in range(10):t = Thread(target=task)t.start()t.join()stop = time.time()print(stop - start)Thread-1 Thread-2 Thread-3 Thread-4 Thread-5 Thread-6 Thread-7 Thread-9 Thread-8 Thread-10 4.001999855041504 View Code6、寫一個程序 ,包含一個名為hello的函數,函數的功能是打印字符串“Hello, World!”,該函數必須在程序執行30秒之后才開始執行(不能使用time.sleep());
from threading import Timer def hello(name):print('%s say '%name,'Hello World!')if __name__ == "__main__":t = Timer(5,hello,args=('alice',))t.start()---------------------------------------------
from threading import Thread,Timer,currentThread,Event
def task():
event.wait()
print('Hello, World!')
if __name__ == '__main__':
event=Event()
t=Thread(target=task)
t.start()
event.wait(5)
event.set() ?
7、寫一個程序,利用queue實現進程間通信;
# from multiprocessing import Process,Queue # import time,random,os # def consumer(q,name): # while True: # res=q.get() # if res is None:break # time.sleep(random.randint(1,3)) # print(f"{name},{res}") # # def producer(q,name,food): # for i in range(3): # # res=f"{food},{i}" # q.put(res) # print(f"{name}生產了{i}") # # if __name__ == '__main__': # q=Queue() # #生產者們:即廚師們 # p1=Process(target=producer,args=(q,'egon','包子')) # # #消費者們:即吃貨們 # c1=Process(target=consumer,args=(q,'alex')) # # #開始 # p1.start() # c1.start() # p1.join() # q.put(None) # print('主')# --------------------------------------------------------------------- from multiprocessing import Process,JoinableQueue import time,random,os def producer(q,name):for i in range(3):res=f"{name},{i}"q.put(res)print(res) def consumer(q,name):while True:res=q.get()print(f'{name} eating---',res)q.task_done()if __name__ == '__main__':q=JoinableQueue()p1=Process(target=producer,args=(q,'aa'))c1=Process(target=consumer,args=(q,'bb'))c1.daemon=Truep1.start()c1.start()p1.join()print('主')8、寫一個程序,利用pipe實現進程間通信;
from multiprocessing import Process,Pipe def task(conn):conn.send('hello world')conn.close()if __name__ == "__main__":parent_conn,child_conn = Pipe()p = Process(target=task,args=(child_conn,))p.start()p.join()print(parent_conn.recv()) View Code9、使用selectors模塊創建一個處理客戶端消息的服務器程序;
# server blocking IO import socket server = socket.socket(socket.AF_INET,socket.SOCK_STREAM) server.bind(('127.0.0.1',8080)) server.listen(5) while True:conn,addr = server.accept()print(addr)while True:try:data = conn.recv(1024)if not data: breakconn.send(data.upper())except Exception as e:print(e)break# server IO多路復用 selectors 會根據操作系統選擇select poll epoll import socket import selectors sel = selectors.DefaultSelector() def accept(server_fileobj,mask):conn,addr = server_fileobj.accept()print(addr)sel.register(conn,selectors.EVENT_READ,read)def read(conn,mask):try:data = conn.recv(1024)if not data:print('closing..',conn)sel.unregister(conn)conn.close()returnconn.send(data.upper())except Exception:print('closeing...',conn)sel.unregister(conn)conn.close()server_fileobj = socket.socket(socket.AF_INET,socket.SOCK_STREAM) server_fileobj.bind(('127.0.0.1',8080)) server_fileobj.listen(5) server_fileobj.setblocking(False) sel.register(server_fileobj,selectors.EVENT_READ,accept) while True:events = sel.select()for sel_obj,mask in events:callback = sel_obj.datacallback(sel_obj.fileobj,mask)# client # -*- coding:utf-8 -*- import socket client = socket.socket(socket.AF_INET,socket.SOCK_STREAM) client.connect(('127.0.0.1',8080)) while True:msg = input('>>>:').strip()if not msg:continueclient.send(msg.encode('utf-8'))data = client.recv(1024)print(data.decode('utf-8')) View Code10、使用socketserver創建服務器程序時,如果使用fork或者線程服務器,一個潛在的問題是,惡意的程序可能會發送大量的請求導致服務器崩潰,請寫一個程序,避免此類問題;
# server socketserver 模塊內部使用IO多路復用 和多進程/多線程 import socketserver class Handler(socketserver.BaseRequestHandler):def handle(self):print('new connection:',self.client_address)while True:try:data = self.request.recv(1024)if not data:breakprint('client data:',data.decode())self.request.send(data.upper())except Exception as e:print(e)breakif __name__ == "__main__":server = socketserver.ThreadingTCPServer(('127.0.0.1',8080),Handler)server.serve_forever() View Code?
11、寫一個程序,要求用戶輸入用戶名和密碼,要求密碼長度不少于6個字符,且必須以字母開頭,如果密碼合法,則將該密碼使用md5算法加密后的十六進制概要值存入名為password.txt的文件,超過三次不合法則退出程序;
def start():count = 3while count > 0:name = input('>>').strip()pwd = input('>>').strip()if len(pwd) >= 6 and pwd[0].isalpha():# isalpha() 方法檢測字符串是否只由字母組成。pwd_md5 = hashlib.md5(pwd.encode('utf-8')).hexdigest()print('輸入成功')obj = {'user_name': name, 'pass_word': pwd_md5}with open('password.txt','a',encoding='utf-8')as f:json.dump(obj,f)exit()else:if count == 0:print('三次錯誤')exit()count -=1print(f'輸入錯誤還有{count}次機會')continueif __name__ == '__main__':import hashlib,jsonstart() View Code?12、寫一個程序,使用socketserver模塊,實現一個支持同時處理多個客戶端請求的服務器,要求每次啟動一個新線程處理客戶端請求;
python中的socketserver模塊,主要是用來提供服務器類,并且提供異步處理的能力。
服務端: import socketserver class Handler(socketserver.BaseRequestHandler):def handle(self):print('new connection:', self.client_address)while True:try:data = self.request.recv(1024)if not data: breakprint('client data:', data.decode())self.request.send(data.upper())except Exception as e:print(e)breakif __name__ == "__main__":server = socketserver.ThreadingTCPServer(('127.0.0.1', 8082), Handler)server.serve_forever()客戶端 模擬多個線程 ---客戶端發送消息def start(ip_port):client = socket.socket(socket.AF_INET,socket.SOCK_STREAM)client.connect(ip_port)client.send(f"{currentThread().getName()} hello".encode('utf-8'))data = client.recv(1024)print(data.decode('utf-8'))if __name__ == '__main__':import socketfrom threading import Thread,currentThreadip_port = ('127.0.0.1',8082)for i in range(20):t = Thread(target=start,args=(ip_port,))t.start()?13、請使用協程寫一個消費者生產者模型;
# def consumer(): # while True: # x = yield # print('消費:',x) # # def producter(): # c = consumer() # next(c) # for i in range(10): # print('生產:',i) # c.send(i) # # if __name__ == '__main__': # producter()import gevent from gevent import monkey;monkey.patch_all() def consumer(i):print('消費',i) def producter(i):print('生產',i)if __name__ == '__main__':for i in range(10):g1 = gevent.spawn(producter,i)g2 = gevent.spawn(consumer,i)g1.join()g2.join() View Code?
轉載于:https://www.cnblogs.com/foremostxl/p/9740126.html
總結
以上是生活随笔為你收集整理的并发编程-单元练习题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ocrosoft Contest1316
- 下一篇: 设计登陆需求页面