1. 程式人生 > >行走的小菜頭

行走的小菜頭

from threading import Thread
import time

#1. 如果多個執行緒執行的都是同一個函式的話,各自之間不會有影響,各是個的
def test(arg):
    time.sleep(1)
    print("thread"+str(arg))


for i in range(5):  #5個執行緒同時執行
    t = Thread(target=test,args=(i,))
    t.start()


結果:
thread0
thread2
thread1
thread3
thread4


執行緒程式碼的封裝:

import threading,time

class MyThread(threading.Thread):
    def run(self):
        for i in range(5):
            time.sleep(1)
            print('I`m '+self.name+ '程序 '+str(i)) #name當前的執行緒名


if __name__=='__main__':
    t=MyThread()
    t.start()



多執行緒間共享全域性變數,造成對共享資料的出錯,使用互斥鎖,給各個程序上鎖,當這個程序釋放後,下一個程序才開始執行,依次迴圈,保護好共享的安全性。
#多執行緒間共享資料出錯:
from threading import Thread
import time


g_num = 0  #全域性變數

def test1():
    global g_num
    for i in range(1000000):
        g_num += 1
    print("---test1---g_num=%d"%g_num)

def test2():
    global g_num
    for i in range(1000000):
        g_num += 1
    print("---test2---g_num=%d"%g_num)


p1 = Thread(target=test1)
p1.start()

#time.sleep(3) #取消遮蔽之後 再次執行程式,資料就不會變化,因為test1程序在3s內足夠執行完,不造成資料的錯亂。

p2 = Thread(target=test2)
p2.start()

print("---g_num=%d---"%g_num)



結果:
---g_num=234497---
---test1---g_num=1143699
---test2---g_num=1342951
#使用互斥鎖:
from threading import Thread, Lock
import time

g_num = 0

def test1():
    global g_num
    #這個執行緒和test2執行緒都在搶著 對這個鎖 進行上鎖,如果有一方成功的上鎖,那麼導致另外一方會堵塞(一直等待)到這個鎖被解開為止
    mutex.acquire()
    for i in range(1000000):
        g_num += 1
    mutex.release()
#用來對mutex指向的這個鎖 進行解鎖,,,只要開了鎖,那麼接下來會讓所有因為這個鎖 被上了鎖 而堵塞的執行緒 進行搶著上鎖

    print("---test1---g_num=%d"%g_num)

def test2():
    global g_num
    mutex.acquire()
    for i in range(1000000):
        g_num += 1
    mutex.release()

    print("---test2---g_num=%d"%g_num)


#建立一把互斥鎖,這個鎖預設是沒有上鎖的
mutex = Lock()

p1 = Thread(target=test1)
p1.start()

#time.sleep(3) #取消遮蔽之後 再次執行程式,結果會不一樣,,,為啥呢?

p2 = Thread(target=test2)
p2.start()

print("---g_num=%d---"%g_num)



#互斥鎖放到for迴圈裡,最後是200萬,第一個都在執行
  • 同步:

同步就是協同步調,按預定的先後次序進行執行如:你說完,我再說。

如程序,執行緒同步,可理解為程序或執行緒甲和乙一塊配合,A執行到一定程度時要依靠乙的某個結果,於是停下來,示意乙執行;乙依言執行,再將結果給阿; A再繼續操作。

from threading import Thread,Lock
from time import sleep

class Task1(Thread):
    def run(self):
        while True:
            if lock1.acquire():
                print("------Task 1 -----")
                sleep(0.5)
                lock2.release()

class Task2(Thread):
    def run(self):
        while True:
            if lock2.acquire():
                print("------Task 2 -----")
                sleep(0.5)
                lock3.release()

class Task3(Thread):
    def run(self):
        while True:
            if lock3.acquire():
                print("------Task 3 -----")
                sleep(0.5)
                lock1.release()

#使用Lock創建出的鎖預設沒有“鎖上”
lock1 = Lock()
#建立另外一把鎖,並且“鎖上”
lock2 = Lock()
lock2.acquire()
#建立另外一把鎖,並且“鎖上”
lock3 = Lock()
lock3.acquire()

t1 = Task1()
t2 = Task2()
t3 = Task3()

t1.start()
t2.start()
t3.start()


結果:
------Task 1 -----
------Task 2 -----
------Task 3 -----
------Task 1 -----
------Task 2 -----
------Task 3 -----
------Task 1 -----
------Task 2 -----
------Task 3 -----
------Task 1 -----
------Task 2 -----
------Task 3 -----

 蟒的佇列模組中提供了同步的,執行緒安全的佇列類,包括FIFO(先入先出)佇列佇列,LIFO(後入先出)佇列LifoQueue,和優先順序佇列PriorityQueue.Queue可以使用佇列來實現執行緒間的同步。

#佇列解耦, - 解決死鎖問題

非同步:

from multiprocessing import Pool
import time
import os

 #非同步的理解:主程序正在做某件事情,突然 來了一件更需要立刻去做的事情,
 #那麼這種,在父程序去做某件事情的時候 並不知道是什麼時候去做,的模式 就稱為非同步

def test():
    print("---程序池中的程序---pid=%d,ppid=%d--"%(os.getpid(),os.getppid()))
    for i in range(3):
        print("----%d---"%i)
        time.sleep(1)
    return "hahah"

def test2(args):
    print("---callback func--pid=%d"%os.getpid())
    print("---callback func--args=%s"%args)  #hahah



if __name__ == '__main__':

    pool = Pool(3)
    pool.apply_async(func=test,callback=test2)

    time.sleep(5)
    print("----主程序-pid=%d----"%os.getpid())



結果:
---程序池中的程序---pid=7664,ppid=5612--
----0---
----1---
----2---
---callback func--pid=5612
---callback func--args=hahah
----主程序-pid=5612----