互斥锁
互斥锁Lock
也是一种阻塞,可以保证共享数据操作的完整性。保证在任一时刻,只能有一个线程访问该对象
from multiprocessing import Process
from threading import Thread
from multiprocessing import Lock # 进程锁
# from threading import Lock # 线程锁
import time
def a(lock):
lock.acquire() # 加锁
print("p1前")
time.sleep(1)
print("p1后")
lock.release() # 解锁
def b(lock):
lock.acquire() # 加锁
print("p2前")
time.sleep(1)
print("p2后")
lock.release() # 解锁
if __name__ == '__main__':
lock = Lock() # 创建一个锁
p1 = Process(target=a,args=(lock,))
p2 = Process(target=b,args=(lock,))
p1.start()
p2.start()
死锁
是指两个或两个以上的进程或线程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程
from threading import Thread
from threading import Lock
import time
locka = Lock()
lockb = Lock()
class Te(Thread):
def run(self):
self.a()
self.b()
def a(self):
locka.acquire()
print(f"{self.name}拿到A锁")
lockb.acquire()
print(f"{self.name}拿到B锁")
lockb.release()
print(f"{self.name}释放B锁")
locka.release()
print(f"{self.name}释放A锁")
def b(self):
lockb.acquire()
print(f"{self.name}拿到B锁")
time.sleep(0.1)
locka.acquire()
print(f"{self.name}拿到A锁")
locka.release()
print(f"{self.name}释放A锁")
lockb.release()
print(f"{self.name}释放B锁")
if __name__ == '__main__':
for i in range(3):
t = Te()
t.start()
递归锁
递归锁RLock
可以解决死锁问题,递归锁有一个计数器,每次上锁都会加一,解锁会减一,直到计数器为零时其他进程才可以进行抢锁
from threading import Thread
from threading import RLock
import time
locka = lockb = RLock() # 创建格式
class Te(Thread):
def run(self):
self.a()
self.b()
def a(self):
locka.acquire()
print(f"{self.name}拿到A锁")
lockb.acquire()
print(f"{self.name}拿到B锁")
lockb.release()
print(f"{self.name}释放B锁")
locka.release()
print(f"{self.name}释放A锁")
def b(self):
lockb.acquire()
print(f"{self.name}拿到B锁")
time.sleep(0.1)
locka.acquire()
print(f"{self.name}拿到A锁")
locka.release()
print(f"{self.name}释放A锁")
lockb.release()
print(f"{self.name}释放B锁")
if __name__ == '__main__':
for i in range(3):
t = Te()
t.start()
信号量
Semaphore管理一个内置的计数器,每当调用acquire()时内置计数器-1;调用release() 时内置计数器+1;计数器不能小于0;当计数器为0时,acquire()将阻塞线程直到其他线程调用release()。
from threading import Thread,Semaphore
import time
sem = Semaphore(2)
def a(name):
sem.acquire()
print(name)
time.sleep(2)
sem.release()
if __name__ == '__main__':
for i in range(5):
t = Thread(target=a,args=(f"线程{i}",))
t.start()
GIL全局解释器锁
GIL锁是一个解释器级别的锁,保证了同一时刻只能一个线程进入解释器,jpyhon和pypy都没有GIL锁,保证了cpython解释器的数据资源安全的同时,也使单进程多线程的程序不能利用多核
GIL锁和lock锁的区别
- 两种锁都是互斥锁,GIL锁保护解释器内部资源数据的安全,上锁和释放锁不需要手动操作
- lock锁保护进程或线程中的资源数据安全,是自己定义的,需要自己手动上锁和释放锁