Python入门学习笔记13(线程锁与信号量)

锁的作用是在多个线程访问同一个资源时对资源进行保护,防止多线程操作造成结果不解预测

1.互斥锁

import threading

num = 0

mutex = threading.Lock();

def cal(i):
    #上锁
    mutex.acquire()
    global num
    num += i
    #解锁
    mutex.release()

lst = []
for i in range(5):
    t = threading.Thread(target=cal,args=(i,))
    lst.append(t)
    t.start()

for t in lst:
    t.join()
print(num)

2.可重入锁

可重入锁是用来解决循环加锁造成的死锁问题。

互斥锁连续上锁两次以上便会陷入死锁状态,如果要使用同一把锁进行多次锁操作,必须使用可重入锁RLock。

RLock中维护了一个Lock对象和一个counter,counter中记录了锁acquire的次数,使得可以对锁进行多次的acquire操作。

只有在所有的acquire被release之后,其他线程才能够获得资源。

#如果使用了Lock便会死锁
# mutex = threading.Lock();
mutex = threading.RLock();

num = 0

def plus():
    mutex.acquire()
    print("plus lock")
    global num
    num += 1
    mutex.release()
    print("plus release")

def mimus():
    mutex.acquire()
    print("mimus lock")
    global num
    num -= 1
    mutex.release()
    print("mimus release")

def run():
    mutex.acquire()
    plus()
    print("-----------")
    mimus()
    mutex.release()

for i in range(5):
    t = threading.Thread(target=run)
    t.start()

3.信号量

互斥锁同时允许一个线程访问资源,而信号量同时允许一组线程访问资源。

连接池就是信号量的运用。

import threading
import time
#一个最大为5的信号量
semaphore = threading.BoundedSemaphore(5)

def func(i):
    semaphore.acquire()
    print("member%d访问" %i)
    time.sleep(i)
    semaphore.release()

for i in range(20):
    t= threading.Thread(target = func,args = (i,))
    t.start()

从运行结果可以看出,持续会维持在同时最多只有5个线程可以进行访问,当有信号量release了才会用新的进程递补

原文地址:https://www.cnblogs.com/Hexdecimal/p/9407559.html