Python MultiThread多线程中的Lock用途?
Lock机制通常会使用于,当有多个线程要使用同一个代码资源,且对同一个全域(共享)变数进行修改的时候。
例如当有多个线程要使用同一段程式码资源时,若不想要在使用期间被其他线程拿来同时使用,此时就可以用 锁(Lock) 的机制来确保资源一次只给一个线程运行。
用排队上厕所来比喻吧!
假如今天有一间厕所(function)和一把钥匙(threading.Lock()
),有很多的人(threads)都在排队要大号,先到的人(thread)就可以获得厕所门的钥匙(lock),并且在上厕所的时候会把门锁起来(lock.acquire()
),此时正在排队的其他人就只能在门外等待,直到正在大号的人把门打开将钥匙交出来(lock.release()
),这样下一个人就能拿到这钥匙进入厕所,并把门锁起来以防止他人进入,以此类推~
如何使用Lock?
创建一个lock对象: lock = threading.Lock()
获取使用lock: lock.acquire()
解除释放lock: lock.release()
程式码範例:
import threadingimport timelock = threading.Lock() # 厕所门的钥匙(lock)toilet = [] # 放屎的马桶(list)# 厕所(function)def WC(): lock.acquire() # 使用钥匙将厕所门上锁 toilet.append(f"{threading.current_thread().name}: 拉了第1坨屎") # 将当前的人(线程)所拉的第一屎放进马桶(list)中 time.sleep(0.1) toilet.append(f"{threading.current_thread().name}: 拉了第2坨屎") # 将当前的人(线程)所拉的第二屎放进马桶(list)中 lock.release() # 将厕所门解锁, 并把钥匙放在旁边等下一个人来拿# 产生3位排队大号的人for i in range(3): wc_thread = threading.Thread(target=WC) wc_thread.start() # 第 i 个人开始进厕所大号time.sleep(1) # 等待一秒确保三个人都上完厕所, 且马桶内都有他们排放的屎了print(toilet) # 将马桶内的屎打印出来看排序
输出结果:
使用Lock:
['Thread-1: 拉了第1坨屎', 'Thread-1: 拉了第2坨屎', 'Thread-2: 拉了第1坨屎', 'Thread-2: 拉了第2坨屎', 'Thread-3: 拉了第1坨屎', 'Thread-3: 拉了第2坨屎']
不使用Lock:
['Thread-1: 拉了第1坨屎', 'Thread-2: 拉了第1坨屎', 'Thread-3: 拉了第1坨屎', 'Thread-1: 拉了第2坨屎', 'Thread-3: 拉了第2坨屎', 'Thread-2: 拉了第2坨屎']
由此可知,有使用Lock的马桶(list)结果会是:
先等第一个人(Thread-1)拉完两坨屎后,第二位(Thread-2)和第三位(Thread-3)才会接续继续。
反之,不使用Lock的马桶(list)结果会是:
第一个人(Thread-1)才刚拉完第一坨屎,都还没拉完第二坨,第二位(Thread-2)和第三位(Thread-3)就一起进来各拉了第一坨屎,后续也一起拉了第二坨,等于现在这间厕所内同时有三个人在拉屎。
结论:
当有多个执行绪同时执行lock.acquire()
时,只有一个执行绪能成功获取到锁,并且继续执行程式码,其他的执行绪就只能等待直到锁被释放并获得为止。