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()))

 

總結完成!

 

作者:含笑半步顛√

博客鏈接:https://www.cnblogs.com/lixy-88428977

聲明:本文為博主學習感悟總結,水平有限,如果不當,歡迎指正。如果您認為還不錯,歡迎轉載。轉載與引用請注明作者及出處。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM