💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
<del>当获取线程锁时,此线程独占CPU资源 锁主要用来解决资源竞争问题。 ### Lock锁原语对象 下面的例子,数字顺序变乱是其次;但如果,多个线程同时操作全局变量num会造成最终的结果小于10000。 同时生成10000个线程,线程生成后,运行瞬间结束,所以生成的数字顺序是正常的, 显示结果也是正常的。 当主线程还在生成下一个线程时,上一个子线程就已经结束了,所以不会有资源竞争。 ```python #!/usr/bin/env python # coding=utf-8 from threading import Thread, Lock from time import sleep num = 0 def add(): global num num += 1 print num lock = Lock() for i in range(10000): add_thread = Thread(target=add, args=()) add_thread.start() ``` 在线程中延迟了1秒,当主线程还在生成下一个线程时,上一个子线程还没结束了,生成线程的速度远快于线程结束的速度,造成资源竞争,数字顺序变乱,结果不正常。 ```python from threading import Thread, Lock from time import sleep num = 0 def add(): global num sleep(1) num += 1 print num for i in range(10000): add_thread = Thread(target=add, args=()) add_thread.start() ``` --- 如果想解决上面的问题,可以在对全局变量进行造作时加锁。 实际上,这种做法只能避免资源竞争,但是按顺序输出无法保证 ```python #!/usr/bin/env python # coding=utf-8 from threading import Thread, Lock from time import sleep num = 0 def add(): global num sleep(1) # 加锁后,只有一个线程能获得锁,所以操作变量后立即释放锁 lock.acquire() num += 1 lock.release() print num # 生成锁 lock = Lock() for i in range(10000): add_thread = Thread(target=add, args=()) add_thread.start() ``` --- ### 递归锁RLock 使单一线程可以获得已持有的锁。 产生死锁 说明: ```python #!/usr/bin/env python # coding=utf-8 from threading import Thread, Lock from time import sleep num = 0 num2 = 0 def add(): global num, num2 sleep(1) # 获得一把锁 lock.acquire() num += 1 # 等待自己的上一把锁释放,可是自己一直没有释放。 lock.acquire() num2 += 1 lock.release() lock.acquire() print (num,num2) # 生成锁 lock = Lock() for i in range(10000): add_thread = Thread(target=add, args=()) add_thread.start() ``` 使用RLcok解决死锁问题, RLock使单一线程能够再次获取自己的锁 ```python #!/usr/bin/env python # coding=utf-8 from threading import Thread, RLock from time import sleep num = 0 num2 = 0 def add(): global num, num2 sleep(1) # 获得一把锁 lock.acquire() num += 1 # 获得一把锁 lock.acquire() num2 += 1 # 释放两次 lock.release() lock.release() print num,num2 # 生成锁 lock = RLock() for i in range(10000): add_thread = Thread(target=add, args=()) add_thread.start() ``` ### 使用上下文管理器 使用上下文管理器,可以简化代码。进入该套件之前,上下文管理器会调用acquire()方法,并在完成后调用release()方法。 ~~~ #!/usr/bin/env python # coding=utf-8 #python2 from threading import Thread, RLock from time import sleep num = 0 num2 = 0 def add(): global num, num2 sleep(1) # 获得一把锁 with lock: num += 1 # 获得一把锁 with lock: num2 += 1 print num,num2 # 生成锁 lock = RLock() for i in range(10000): add_thread = Thread(target=add, args=()) add_thread.start() ~~~