#coding=utf-8
from time import sleep
defsing()
:for i in
range(3
):print
("正在唱歌...%d"
%i) sleep(1)
defdance()
:for i in
range(3
):print
("正在跳舞...%d"
%i) sleep(1)
if __name__ ==
'__main__'
: sing(
)#唱歌
dance(
)#跳舞
執行結果:
正在唱歌...0
正在唱歌...1
正在唱歌...2
正在跳舞...0
正在跳舞...1
正在跳舞...2
併發:指的是任務數多餘cpu核數,通過作業系統的各種任務排程演算法,實現用多個任務「一起」執行(實際上總有一些任務不在執行,因為切換任務的速度相當快,看上去一起執行而已)
並行:指的是任務數小於等於cpu核數,即任務真的是一起執行的
1.使用threading模組
單執行緒執行
#coding=utf-8
import time
defsaysorry()
:print
("親愛的,我錯了,我能吃飯了嗎?"
) time.sleep(1)
if __name__ ==
"__main__"
:for i in
range(5
):saysorry(
)
多執行緒執行
#coding=utf-8
import threading
import time
defsaysorry()
:print
("親愛的,我錯了,我能吃飯了嗎?"
) time.sleep(1)
if __name__ ==
"__main__"
:for i in
range(5
):t = threading.thread(target=saysorry)
t.start(
)#啟動執行緒,即讓執行緒開始執行
from threading import thread
import time
g_num =
100def
work1()
:global g_num
for i in
range(3
):g_num +=
1print
("----in work1, g_num is %d---"
%g_num)
defwork2()
:global g_num
print
("----in work2, g_num is %d---"
%g_num)
print
("---執行緒建立之前g_num is %d---"
%g_num)
t1 = thread(target=work1)
t1.start(
)#延時一會,保證t1執行緒中的事情做完
time.sleep(1)
t2 = thread(target=work2)
t2.start(
)
執行結果:
-
--執行緒建立之前g_num is
100---
----
in work1, g_num is
103---
----
in work2, g_num is
103-
--
列表當做實參傳遞到執行緒中
from threading import thread
import time
defwork1
(nums):44
)print
("----in work1---"
,nums)
defwork2
(nums)
:#延時一會,保證t1執行緒中的事情做完
time.sleep(1)
print
("----in work2---"
,nums)
g_nums =[11
,22,33
]t1 = thread(target=work1, args=
(g_nums,))
t1.start(
)t2 = thread(target=work2, args=
(g_nums,))
t2.start(
)
執行結果:
---
-in work1---
[11,22
,33,44
]---
-in work2---
[11,22
,33,44
]
在乙個程序內的所有執行緒共享全域性變數,很方便在多個執行緒間共享資料
缺點就是,執行緒是對全域性變數隨意遂改可能造成多執行緒之間對全域性變數的混亂(即執行緒非安全)
同步就是協同步調,按預定的先後次序進行執行。如:你說完,我再說。
"同"字從字面上容易理解為一起動作
其實不是,"同"字應是指協同、協助、互相配合。
如程序、執行緒同步,可理解為程序或執行緒a和b一塊配合,a執行到一定程度時要依靠b的某個結果,於是停下來,示意b執行;b執行,再將結果給a;a再繼續操作。
解決執行緒同時修改全域性變數的方式
對於上一小節提出的那個計算錯誤的問題,可以通過執行緒同步來進行解決
思路,如下:
系統呼叫t1,然後獲取到g_num的值為0,此時上一把鎖,即不允許其他執行緒操作g_num
t1對g_num的值進行+1
t1解鎖,此時g_num的值為1,其他的執行緒就可以使用g_num了,而且是g_num的值不是0而是1
同理其他執行緒在對g_num進行修改時,都要先上鎖,處理完後再解鎖,在上鎖的整個過程中不允許其他執行緒訪問,就保證了資料的正確性
當多個執行緒幾乎同時修改某乙個共享資料的時候,需要進行同步控制
執行緒同步能夠保證多個執行緒安全訪問競爭資源,最簡單的同步機制是引入互斥鎖。
互斥鎖為資源引入乙個狀態:鎖定/非鎖定
某個執行緒要更改共享資料時,先將其鎖定,此時資源的狀態為「鎖定」,其他執行緒不能更改;直到該執行緒釋放資源,將資源的狀態變成「非鎖定」,其他的執行緒才能再次鎖定該資源。互斥鎖保證了每次只有乙個執行緒進行寫入操作,從而保證了多執行緒情況下資料的正確性。
#建立鎖
mutex = threading.lock(
)#鎖定
mutex.acquire(
)#釋放
mutex.release(
)
注意:
如果這個鎖之前是沒有上鎖的,那麼acquire不會堵塞
如果在呼叫acquire對這個鎖上鎖之前 它已經被 其他執行緒上了鎖,那麼此時acquire會堵塞,直到這個鎖被解鎖為止
當乙個執行緒呼叫鎖的acquire()方法獲得鎖時,鎖就進入「locked」狀態。
每次只有乙個執行緒可以獲得鎖。如果此時另乙個執行緒試圖獲得這個鎖,該執行緒就會變為「blocked」狀態,稱為「阻塞」,直到擁有鎖的執行緒呼叫鎖的release()方法釋放鎖之後,鎖進入「unlocked」狀態。
執行緒排程程式從處於同步阻塞狀態的執行緒中選擇乙個來獲得鎖,並使得該執行緒進入執行(running)狀態。
確保了某段關鍵**只能由乙個執行緒從頭到尾完整地執行
阻止了多執行緒併發執行,包含鎖的某段**實際上只能以單執行緒模式執行,效率就大大地下降了
由於可以存在多個鎖,不同的執行緒持有不同的鎖,並試圖獲取對方持有的鎖時,可能會造成死鎖
多工 執行緒
建立函式 建立執行緒物件,並制定函式 開啟執行緒 import threading import time defwork1 1.定義函式 for i in range 5 print 正在掃地 i time.sleep 1 defmain 測試執行緒的基本使用 2.建立執行緒物件 t1 threa...
多工 執行緒
簡單地說,就是作業系統可以同時執行多個任務。實現多工有多種方式,執行緒 程序 協程。可以簡單理解為同一程序中有多個計數器,每個執行緒的執行時間不確定,而每個程序的時間片相等,執行緒是作業系統排程執行的最小單位.import threadingt1 threading.thread target fu...
多工 執行緒
什麼叫 多工 呢?簡單地說,就是作業系統可以同時執行多個任務。執行緒 1.使用threading模組 import threading defsing pass defdance pass defmain t1 threading.thread target sing t2 threading.th...