首頁 > 後端開發 > Python教學 > 深入理解上篇之 Python的進程和執行緒

深入理解上篇之 Python的進程和執行緒

coldplay.xixi
發布: 2020-11-17 16:25:23
轉載
2579 人瀏覽過

python影片教學欄位介紹進程和執行緒。

深入理解上篇之 Python的進程和執行緒

進程(Process)和執行緒(Thread)都是作業系統中的基本概念,它們之間有一些優劣和差異,那麼在Python中如何使用進程和線程?

CPU

計算機的核心是CPU,它承擔了計算機的所有計算任務,CPU就像一個工廠,時刻在運行著,而操作系統管理著計算機,負責任務的調度、資源的分配與管理。

流程

流程是指在系統中能獨立運作並作為資源分配的基本單位,它是由一組機器指令、資料和堆疊等組成的,是一個能獨立運行的活動實體。

我們打開我們的電腦就會看到進程和線程,點擊我的電腦就可以看到CPU的運算。

從如圖中,CPU總共運行著190個進程,2620個執行緒。例如,當我們再次點選QQ,登陸另一個帳號的時候又會開啟另一個QQ進程。

因此,如果想在電腦登入多個微信。只需要找到你的微信快捷方式,點擊右鍵查看屬性,在目標中複製連結;新建一個記事本,隨便取個名字,雙擊打開後,在其中輸入start ""(注意引號為英文狀態,且前後有空格),將剛複製的連結(也就是微信安裝的路徑)貼進去;然後複製整行,想開幾個微信就貼上幾行;儲存文件,更改後綴名為bat。雙擊運行即可。

深入理解上篇之 Python的進程和執行緒

執行緒

執行緒(Thread)也叫輕量級進程,是作業系統能夠進行運算調度的最小單位,它被包涵在進程之中,是進程中的實際運作單位。

記得阮一峰寫過的部落格:假定工廠的電力有限,一次只能供給一個車間使用。也就是說,一個車間開工的時候,其他車間都必須停工。背後的意義就是,單一CPU一次只能運行一個任務。

行程就好比工廠的車間,它代表CPU所能處理的單一任務。任一時刻,CPU總是運行一個進程,其他進程處於非運行狀態。

線程就好比車間裡的工人。一個行程可以包含多個線程,協同完成一個任務。

總結來說:程式可以包含多個進程,多個進程並發執行,相互獨立,因此,進程也是系統進行資源分配和調度基本單位。專業化來說:進程是指程式執行時的一個實例。執行緒是最小的執行單元,而行程由至少一個執行緒組成。如何調度進程和線程,完全由作業系統決定。

在Python中線程和進程的使用

現在講下在Python線程和進程的使用。

在Python中,透過兩個標準函式庫 threadThreading提供對執行緒的支援,threadingthread進行了封裝。 threading模組中提供了Thread,Lock, RLOCK, Condition等元件

# Thread

在Python中執行緒和行程的使用就是透過Thread這個類別。這個類別在我們的_threadthreading模組中。我們一般透過threading導入。

預設情況下,只要在解釋器中,如果沒有報錯,則表示執行緒可用。

>> from threading import Thread复制代码
登入後複製

以下是Thread類別的常用參數說明和實例方法。

我們看一個官方文件中標準的多執行緒的範例。

import threading
import time
# 定义线程要运行的函数
def func(name):
    # 为了便于观察,睡眠2秒
    time.sleep(2)
    print("My name is %s\t" % name)

# 创建第一个线程的实例,args参数是一个元组,后面必须加逗号分隔
t1 = threading.Thread(target=func, args=("Runsen",))
# 创建第二个线程的实例
t2 = threading.Thread(target=func, args=("Maoli",))
t1.start()
t2.start()
# 先打印线程名 
print(t1.getName())
print(t2.getName())复制代码
登入後複製

由於兩個執行緒是同時運行的,所以print列印處理的結果並沒有換行。

下面我寫了下面的程式碼,加深threading模組的使用。

# -*- coding:utf-8 -*-# time :2019/4/9 21:52# author: Runsenimport threadingimport timedef fun1():
    print('hello')
    time.sleep(2)
    print('Bye')def fun2():
    print('hi')
    time.sleep(2)
    print('OUT')
t1 = threading.Thread(target=fun1)
t2 = threading.Thread(target=fun2)
t1.start()
t2.start()# t1.join()# t2.join()print('主线程完毕')复制代码
登入後複製

下面是輸出結果。

hello
hi
主线程完毕
Bye
OUT复制代码
登入後複製

我们先不加join()来阻塞,t1t2两个线程同时执行,由于位置关系先打印hello,再打印hi,这个时候都sleep2秒钟,但是它sleep2秒钟,主程序还是在执行,所以下面打印print('主线程完毕'),最后才打印ByeOUT

线程间变量的共享

在多线程中,所有变量对于所有线程都是共享的,因此,线程之间共享数据的最大危险在于多个线程同时修改一个变量,那就乱套了,所以我们需要互斥锁,来锁住数据。

代码如上图所示,上面代码中打印的a是1还是2?

答案是:2。因为出现了global关键字,线程间变量的共享,在func函数中的a是全局变量。因此在函数中a的值发生了变化。

下面,我们提高一点点难度,代码如下图所示,还是猜一猜a是啥东西。注意:这里出现了join来阻塞,并且增加了加和减的操作。

相信很多人都认为是0,其实这个a的值是变化的,可能这次是0 ,下次是1,还有可能是1000000,比如,我可以

a就是在[-1000000,1000000]中的一个随机数。

为什么呢?这是因为虽然他们是同时运行的,但是同时在修改我们的a,那就乱了。a在for i in range(1000000),就是遍历了1000000incrdecr的方法都加上一起了,在这1000000次遍历中,不知道有多少加,多少减,比如,我1000000都是加,没有减,a就是1000000,但是这种情况的概率很低。

如果你就是想出现0,其实只需要加一个互斥锁就可以了。这样你加多少次,我就减多少次,加减的次数不会叠加。因此来了lock的用法,具体代码如下图所示。

这个a怎么运行都是 0。因为我们把这个a锁上了,这样就加1000000次,减1000000次,怎么出来都是我们的0。

相关免费学习推荐:python视频教程

以上是深入理解上篇之 Python的進程和執行緒的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:juejin.im
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板