一、互斥锁
-
简介
- 互斥锁为资源引入一个状态:锁定/非锁定。
- 某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。
-
上锁解锁过程
- 当一个线程调用锁的acquire()方法获得锁时,锁就进入锁定状态
- 如果此时另一个线程试图通过acquire()方法获得这个锁,该线程就会被阻塞,直到拥有锁的线程调用锁的release()方法释放该锁,使其处于非锁定状态
-
好处
- 确保了某段关键代码只能由一个线程从头到尾完整地执行
-
坏处
- 阻止了多线程并发执行,包含锁的某段代码实际上只能以单线程模式执行,效率就大大下降
- 可能会造成死锁
二、Lock和RLock的主要区别
-
主要区别
- RLock允许在同一线程中被多次连续acquire,而不会出现死锁情况(注意acquire和release必须成对出现)。
- Lock不允许,否则会出现死锁
from threading import Lock,RLock lock = Lock() rlock = RLock() # 可以执行 with rlock: with rlock: print('RLock锁') with lock: # 会出现死锁 with lock: print('Lock锁')
三、Condition
-
简介
- Condition被称为条件变量,除了提供与Lock类似的acquire和release方法外,还提供了wait和notify等方法
-
wait(timeout=None)
- 该方法执行流程:
- 首先会释放内部占用的锁,同时线程被挂起(进入堵塞状态)
- 直到被notify() 或 notify_all() 唤醒或者超时(设置了timeout参数)
- 一旦被唤醒或超时,该线程将立即重新获取锁,程序继续执行
- 返回值
- 正常被唤醒,返回值为True
- 超时则返回False
- 该方法执行流程:
-
notify(n=1)
- 如果有被挂起的线程,则唤醒n个被挂起的线程
- 如果没有线程被挂起,则该方法调用是一个空操作
-
notify_all()
- 唤醒正在等待本条件变量的所有线程
-
示例(生产者消费者模式)
import threading, time from random import randint class Producer(threading.Thread): def run(self): global L while True: val = randint(0, 100) with lock_con: L.append(val) print(f"生产者:{self.name}, Append:{val}, L = {L}") lock_con.notify() time.sleep(3) class Consumer(threading.Thread): def run(self): global L while True: with lock_con: if len(L) == 0: print("队列为空,请等待。。。") lock_con.wait() print('>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>') print(f"消费者: {self.name}, Delete: {L[0]}") del L[0] time.sleep(0.5) if __name__ == '__main__': L = [] # 消费物队列 lock_con = threading.Condition() threads = [] # 若干个生产者线程 for i in range(3): threads.append(Producer()) threads.append(Consumer()) for t in threads: t.start() for t in threads: t.join()
标签:lock,RLock,threading,线程,Lock,print From: https://www.cnblogs.com/eliwang/p/17053048.html