1. 程式人生 > >並發編程---死鎖||遞歸鎖---信號量---Event事件---定時器

並發編程---死鎖||遞歸鎖---信號量---Event事件---定時器

遞歸 spa sleep 事件 lang tin lap 計數器 name

死鎖

互斥鎖:Lock(),互斥鎖只能acquire一次

遞歸鎖: RLock(),可以連續acquire多次,每acquire一次計數器+1,只有計數為0時,才能被搶到acquire

技術分享圖片
# 死鎖
from threading import Thread,Lock
import time

mutexA = Lock()
mutexB = Lock()

class MyThread(Thread):
    def run(self):
        self.f1()
        self.f2()

    def f1(self):
        mutexA.acquire()
        
print(%s 拿到了A鎖 %self.name) mutexB.acquire() print(%s 拿到了B鎖 % self.name) mutexB.release() mutexA.release() def f2(self): mutexB.acquire() print(%s 拿到了B鎖 % self.name) time.sleep(0.1) mutexA.acquire() print(%s 拿到了A鎖 % self.name) mutexB.release() mutexA.release()
if __name__ == __main__: for i in range(10): t=MyThread() t.start() ‘‘‘ 打印結果: Thread-1 拿到了A鎖 Thread-1 拿到了B鎖 Thread-1 拿到了B鎖 Thread-2 拿到了A鎖 ‘‘‘
死鎖 技術分享圖片
#互斥鎖只能acquire一次
from threading import Thread,Lock
mutexA = Lock()
mutexA.acquire()
mutexA.release()

#遞歸鎖:可以連續acquire多次,每acquier一次計數器就+1,只有計數為0時,才能被其他線程強到
from threading import Thread,RLock import time mutexB = mutexA = RLock() class MyThread(Thread): def run(self): self.f1() self.f2() def f1(self): mutexA.acquire() print(%s 拿到了A鎖 %self.name) mutexB.acquire() print(%s 拿到了B鎖 % self.name) mutexB.release() mutexA.release() def f2(self): mutexB.acquire() print(%s 拿到了B鎖 % self.name) time.sleep(2) mutexA.acquire() print(%s 拿到了A鎖 % self.name) mutexB.release() mutexA.release() if __name__ == __main__: for i in range(10): t=MyThread() t.start() ‘‘‘ 打印結果: Thread-1 拿到了A鎖 Thread-1 拿到了B鎖 Thread-1 拿到了B鎖 Thread-1 拿到了A鎖 Thread-2 拿到了A鎖 Thread-2 拿到了B鎖 Thread-2 拿到了B鎖 Thread-2 拿到了A鎖 Thread-4 拿到了A鎖 Thread-4 拿到了B鎖 Thread-4 拿到了B鎖 Thread-4 拿到了A鎖 Thread-6 拿到了A鎖 Thread-6 拿到了B鎖 Thread-6 拿到了B鎖 Thread-6 拿到了A鎖 Thread-8 拿到了A鎖 Thread-8 拿到了B鎖 Thread-8 拿到了B鎖 Thread-8 拿到了A鎖 Thread-10 拿到了A鎖 Thread-10 拿到了B鎖 Thread-10 拿到了B鎖 Thread-10 拿到了A鎖 Thread-5 拿到了A鎖 Thread-5 拿到了B鎖 Thread-5 拿到了B鎖 Thread-5 拿到了A鎖 Thread-9 拿到了A鎖 Thread-9 拿到了B鎖 Thread-9 拿到了B鎖 Thread-9 拿到了A鎖 Thread-7 拿到了A鎖 Thread-7 拿到了B鎖 Thread-7 拿到了B鎖 Thread-7 拿到了A鎖 Thread-3 拿到了A鎖 Thread-3 拿到了B鎖 Thread-3 拿到了B鎖 Thread-3 拿到了A鎖 ‘‘‘
遞歸鎖

信號量

信號量也是一把鎖,可以指定信號量為5,對比互斥鎖同一時間只能有一個任務搶到鎖去執行

信號量同一時間可以有5個任務拿到鎖去執行

信號量:同一時間有多個線程在進行

技術分享圖片
from threading import Thread,Semaphore,currentThread
import time,random

sm=Semaphore(3) #廁所的坑

def task():
    # sm.acquire()
    # print(‘%s in‘ %currentThread.getName())
    # sm.release()
    with sm:
        print(%s in %currentThread().getName())
        time.sleep(random.randint(2,3))

if __name__ == __main__:
    for i in range(10):
        t=Thread(target=task)
        t.start()
‘‘‘
打印結果:
Thread-1 in
Thread-2 in
Thread-3 in

Thread-4 in

Thread-5 in
Thread-6 in

Thread-7 in

Thread-9 in
Thread-8 in
Thread-10 in
‘‘‘
信號量

Event事件

event.isSet(): 返回event的狀態值
event.wait():如果 event.isSet()==False將阻塞線程
event.set():  設置event的狀態值為True,所有阻塞池的線程激活進入就緒狀態,等待操作系統調度
event.clear():  恢復event的狀態值為False
技術分享圖片
from threading import Thread,Event
import time

event = Event()
# event.wait() 在原地等,指導執行到event.set()
# event.set() 等待結束

def student(name):
    print(學生%s 正在聽課 %name)
    event.wait(2)
    print(學生%s 課間活動 %name)

def teacher(name):
    print(老師%s 正在授課 %name)
    time.sleep(5)
    event.set()

if __name__ == __main__:
    stu1 = Thread(target=student,args=(alex,))
    stu2 = Thread(target=student,args=(yang,))
    stu3 = Thread(target=student,args=(hang,))
    tea1 = Thread(target=teacher,args=(ding,))

    stu1.start()
    stu2.start()
    stu3.start()
    tea1.start()
‘‘‘
打印結果:
學生alex 正在聽課
學生yang 正在聽課
學生hang 正在聽課
老師ding 正在授課
學生hang 課間活動
學生yang 課間活動
學生alex 課間活動
‘‘‘


#設置連接的超時時間
from threading import Thread,Event,currentThread
import time

event = Event()

def conn():
    n=0
    while not event.is_set():
        if n == 3:
            print(%s try too many %currentThread().getName())
            return
        print(%s try %s %(currentThread().getName(),n))
        event.wait(0.5)
        n+=1


    print(%s is connecting %currentThread().getName())

def check():
    print(%s is checking %currentThread().getName())
    time.sleep(5)
    event.set()

if __name__ == __main__:
    for i in range(3):
        t=Thread(target=conn)
        t.start()
    t=Thread(target=check)
    t.start()
‘‘‘
打印結果:
Thread-1 try 0
Thread-2 try 0
Thread-3 try 0
Thread-4 is checking
Thread-1 try 1
Thread-3 try 1
Thread-2 try 1
Thread-1 try 2
Thread-3 try 2
Thread-2 try 2
Thread-1 try too many
Thread-3 try too many
Thread-2 try too many
‘‘‘
Event

定時器

定時器:隔一段時間,執行一個任務,每啟動一個定時器,就等於啟動一個線程

t=Timer(5,task,args=(‘egon‘,))

t.start()

t.cancel()

技術分享圖片
# from  threading import Timer
#
# def task(name):
#     print(‘hello %s‘ %name)
#
# t=Timer(5,task,args=(‘egon‘,))
# t.start()

#驗證碼
from threading import Timer
import random

class Code:
    def __init__(self):
        self.make_cache()

    def make_cache(self,interval=60):
        self.cache = self.make_code()
        print(self.cache)
        self.t = Timer(interval,self.make_cache)
        self.t.start()

    def make_code(self,n=4):
        res=‘‘
        for i in range(n):
            s1 = str(random.randint(0,9))
            s2 = chr(random.randint(65,90))
            res+=random.choice([s1,s2])
        return res

    def check(self):
        while True:
            code = input(輸入你的驗證碼>>: ).strip()
            if code.upper() == self.cache:
                print(驗證碼輸入正確)
                self.t.cancel()
                break

obj=Code()
obj.check()

‘‘‘
打印結果:
X095
輸入你的驗證碼>>: X095
驗證碼輸入正確
‘‘‘
定時器

並發編程---死鎖||遞歸鎖---信號量---Event事件---定時器