在开发的过程中要注意有些操作默认都是 线程安全的(内部集成了锁的机制),我们在使用的时无需再通过锁再处理,例如:
import threading data_list = [] lock_object = threading.RLock() def task(): print("开始") for i in range(1000000): data_list.append(i) print(len(data_list)) for i in range(2): t = threading.Thread(target=task) t.start()所以,要多注意看一些开发文档中是否标明线程安全。
4. 线程锁在程序中如果想要自己手动加锁,一般有两种:Lock 和 RLock。
Lock,同步锁。
import threading num = 0 lock_object = threading.Lock() def task(): print("开始") lock_object.acquire() # 第1个抵达的线程进入并上锁,其他线程就需要再此等待。 global num for i in range(1000000): num += 1 lock_object.release() # 线程出去,并解开锁,其他线程就可以进入并执行了 print(num) for i in range(2): t = threading.Thread(target=task) t.start()
RLock,递归锁。
import threading num = 0 lock_object = threading.RLock() def task(): print("开始") lock_object.acquire() # 第1个抵达的线程进入并上锁,其他线程就需要再此等待。 global num for i in range(1000000): num += 1 lock_object.release() # 线程出去,并解开锁,其他线程就可以进入并执行了 print(num) for i in range(2): t = threading.Thread(target=task) t.start()RLock支持多次申请锁和多次释放;Lock不支持。例如:
import threading import time lock_object = threading.RLock() def task(): print("开始") lock_object.acquire() lock_object.acquire() print(123) lock_object.release() lock_object.release() for i in range(3): t = threading.Thread(target=task) t.start() import threading lock = threading.RLock() # 程序员A开发了一个函数,函数可以被其他开发者调用,内部需要基于锁保证数据安全。 def func(): with lock: pass # 程序员B开发了一个函数,可以直接调用这个函数。 def run(): print("其他功能") func() # 调用程序员A写的func函数,内部用到了锁。 print("其他功能") # 程序员C开发了一个函数,自己需要加锁,同时也需要调用func函数。 def process(): with lock: print("其他功能") func() # ----------------> 此时就会出现多次锁的情况,只有RLock支持(Lock不支持)。 print("其他功能") 5.死锁死锁,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象。
import threading num = 0 lock_object = threading.Lock() def task(): print("开始") lock_object.acquire() # 第1个抵达的线程进入并上锁,其他线程就需要再此等待。 lock_object.acquire() # 第1个抵达的线程进入并上锁,其他线程就需要再此等待。 global num for i in range(1000000): num += 1 lock_object.release() # 线程出去,并解开锁,其他线程就可以进入并执行了 lock_object.release() # 线程出去,并解开锁,其他线程就可以进入并执行了 print(num) for i in range(2): t = threading.Thread(target=task) t.start() import threading import time lock_1 = threading.Lock() lock_2 = threading.Lock() \'\'\' 两个线程都有一个锁却都要获得对方的锁,产生了死锁现象 \'\'\' def task1(): lock_1.acquire() time.sleep(1) lock_2.acquire() print(11) lock_2.release() print(111) lock_1.release() print(1111) def task2(): lock_2.acquire() time.sleep(1) lock_1.acquire() print(22) lock_1.release() print(222) lock_2.release() print(2222) t1 = threading.Thread(target=task1) t1.start() t2 = threading.Thread(target=task2) t2.start() 6.线程池Python3中官方才正式提供线程池。
线程不是开的越多越好,开的多了可能会导致系统的性能更低了,例如:如下的代码是不推荐在项目开发中编写。