python_並行與併發、多線程

python_並行與併發、多線程

問題一: 計算機是如何執行程序指令的?

問題二: 計算機如何實現併發的?

輪詢調度實現併發執行 程序1-8輪詢完成,纔再CPU上運行

問題三: 真正的並行需要依賴什麼?

並行需要的核心條件

 

 

多進程實現並行

問題一: 什麼是進程?

計算機程序是存儲在磁盤上的文件。

  只有把它們加載到內存中,並被操作系統調用 它們纔會擁有其自己的生命週期。

進程表示一個正在執行的程序。

  每個進程都有獨立地址空間以及其他的輔助數據

進程(Process)

  是計算機中已運行程序的實例

 

問題二: 如何在Python中使用進程?

複製代碼

import multiprocessing   # 導入進程模塊
import datetime
import time

def func(data):

    while True:
        print(datetime.datetime.now())

        sum = data + 100
        print(sum)
        time.sleep(2)

        print(datetime.datetime.now())

if __name__ == '__main__':

    p = multiprocessing.Process(target=func, args=(123,))    # 創建一個進程,args傳參 必須是元組
    p.start()    # 運行線程p

    while True:
        time.sleep(2)
        print("我是主進程")

複製代碼

 

進程使用步驟

問題三: 多進程實現並行的必要條件是什麼?

總進程數量不多於 CPU核心數量!

如果不滿足,那麼運行的程序都是 輪詢調度產生的假象。

 

 

多線程實現併發

 問題一:什麼是線程?

線程被稱作輕量級進程。
  線程是進程中的一個實體,操作系統不會爲進程分配內存空間,它只有一點在運行中必不可少的資源
線程被包含在進程中,是進程中的實際運作單位
  同一個進程內的多個線程會共享相同的上下文,
  也就是共享資源(內存和數據)。
線程(thread)
  是操作系統能夠進行運算調度的最小單位





 

問題二: 如何在Python中使用線程?

複製代碼

import multiprocessing  # 引用進程模塊
import threading    # 引用線程模塊
import time

def func(data):
    while True:
        time.sleep(1)
        data += 1
        print(data)

# mult = multiprocessing.Process(target=func, args=(1314,))
# mult.start()  # 運行進程

thre = threading.Thread(target=func, args=(500,))   # 創建一個線程
thre.start()  # 運行線程

print("這是主進程")

複製代碼

 

進程使用步驟

 

問題三: 爲什麼多線程不是並行?

 穩定性
  進程具有獨立的地址空間,一個進程崩潰後,不會對其它進程產生影響。
  線程共享地址空間,一個線程非法操作共享數據崩潰後,整個進程就崩潰了。
 創建開銷
  創建進程操作系統是要分配內存空間和一些其他資源的。開銷很大
  創建線程操作系統不需要再單獨分配資源,開銷較小
 切換開銷
  不同進程直接是獨立的, 切換需要耗費較大資源
  線程共享進程地址空間, 切換開銷小







 

 

GIL鎖(線程鎖)

Python在設計的時候,還沒有多核處理器的概念。
因此,爲了設計方便與線程安全,直接設計了一個鎖。
這個鎖要求,任何進程中,一次只能有一個線程在執行。


因此,並不能爲多個線程分配多個CPU。
所以Python中的線程只能實現併發,
而不能實現真正的並行。



但是Python3中的GIL鎖有一個很棒的設計,
在遇到阻塞(不是耗時)的時候,會自動切換線程。

 

很多庫是基於GIL鎖寫的,取消代價太大
進程可以實現並行和併發
線程只能實現併發

遇到阻塞就自動切換。
我們可以利用這種機制來
充分利用CPU

 

那麼最後:

使用多進程與多線程來實現併發服務器

 

使用多進程與多線程實現併發服務器的關鍵點
關鍵點一: 多進程是並行執行,
                 相當於分別獨立得處理各個請求。
關鍵點二: 多線程,雖然不能並行運行,
                 但是可以通過避開阻塞切換線程
                 來實現併發的效果,並且不浪費cpu




 

服務端實現代碼:

複製代碼

import threading  # 創建一個線程
import socket

server = socket.socket()
server.bind(('0.0.0.0', 8888))
server.listen() # 監聽

def workon(conn):
    while True:
        data = conn.recv(1024)

        if data == b'':
            conn.close()
            break
        else:
            print("接收到的消息: {}".format(data.decode()))
            conn.send(data)

# 主線程
while True:
    conn, addr = server.accept()
    print("{}正在連接".format(addr))

    # 線程去處理消息
    p = threading.Thread(target=workon, args=(conn,))
    p.start()

複製代碼

客戶端代碼:

複製代碼

import socket

click = socket.socket()
click.connect(('127.0.0.1', 8888))

while True:
     data = input("請輸入你要發送的數據:")
     click.send(data.encode())
     print("接收到的消息: {}".format(click.recv(1024).decode()))

複製代碼

 

總結完成!

python_並行與併發、多線程

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章