1.1 线程的背景知识
import threading # 导入线程相关的模块
t = threading.current_thread() # 返回当前线程
print(t) # 主线程执行
print(t.getName()) # 线程名字
print(t.ident) # 线程ID
print(t.isAlive()) # 线程是否存活
1 import threading # 导入线程相关的模块 2 t = threading.current_thread() # 返回当前线程 3 print(t) # 主线程执行 4 print(t.getName()) # 线程名字 5 print(t.ident) # 线程ID 6 print(t.isAlive()) # 线程是否存活
1.2 创建线程
import threading # 导入线程相关的模块
my_thread = threading.Thread()
print(my_thread)
print(my_thread.getName()) # 线程名字
print(my_thread.ident) # 线程ID
print(my_thread.isAlive()) # 线程是否存活
# 重命名线程名字
my_thread = threading.Thread(name='my_thread')
print("重命名:",my_thread.getName()) # 线程名字
1 import threading # 导入线程相关的模块 2 my_thread = threading.Thread() 3 print(my_thread) 4 print(my_thread.getName()) # 线程名字 5 print(my_thread.ident) # 线程ID 6 print(my_thread.isAlive()) # 线程是否存活 7 # 重命名线程名字 8 my_thread = threading.Thread(name='my_thread') 9 print("重命名:",my_thread.getName()) # 线程名字
创建线程的目的是告诉它帮助我们做些什么,做些什么通过参数 target
传入,参数类型为 callable
,函数就是可调用的:
import threading #具体做啥事,写在函数中 def run(number): #输出线程名与次数 print(threading.currentThread().getName(),number) if __name__ == '__main__': for i in range(10): # 指明具体的方法和方法需要的参数 my_thread = threading.Thread(target=run, args=(i,)) # 启动线程 my_thread.start()
1.3 交替获得CPU时间片
开辟3个线程,装到 threads 中:
1 import time 2 from datetime import datetime 3 import threading 4 def print_time(): 5 for _ in range(5): # 在每个线程中打印5次 6 time.sleep(0.1) # 模拟打印前的相关处理逻辑 7 print('当前线程%s,打印结束时间为:%s\n' % (threading.current_thread().getName(),datetime.today())) 8 9 threads = [threading.Thread(name='t%d'%(i,), target=print_time) for i in range(3)] 10 11 [t.start() for t in threads]
打印结果如下, t0 , t1 , t2 三个线程,根据操作系统的调度算法,轮询获得CPU时间片,注意观察,t0,t2 线程可能被连续调度,从而获得时间片。
1.4 多线程抢夺同一个变量
多线程编程,存在抢夺同一个变量的问题。假如创建的10个线程同时竞争全局变量 a。
import threading a = 0 def add(): global a a += 1 # 等差 +1 print("%s adds a to 1:%d"%(threading.current_thread().getName(), a)) threads = [threading.Thread(name = 't%d' %(i,), target=add) for i in range(10)] print(threads) [t.start() for t in threads]
可以看见结果预想的一样。但如果中间sleep沉睡,那会变得怎么样?
1 mport threading 2 import time 3 a = 0 4 def add(): 5 global a 6 a += 1 # 等差 +1 7 time.sleep(0.2) # 延时0.2秒,模拟写入所需时间 8 print("%s adds a to 1:%d"%(threading.current_thread().getName(), a)) 9 10 threads = [threading.Thread(name = 't%d' %(i,), target=add) for i in range(10)] 11 [t.start() for t in threads]
1 import threading 2 import time 3 a = 0 4 def add(): 5 global a 6 tmp = a + 1 # 等差 +1 7 time.sleep(0.2) # 延时0.2秒,模拟写入所需时间 8 a = tmp 9 print("%s adds a to 1:%d"%(threading.current_thread().getName(), a)) 10 11 threads = [threading.Thread(name = 't%d' %(i,), target=add) for i in range(10)] 12 [t.start() for t in threads]
看到,10个线程全部运行后, a 的值只相当于一个线程执行的结果。可以看见延时过后,CPU立即分配计算资源给其他线程,所以输出的进程顺序是无序的。直到分配给所有线程后,根据结果反映出,0.2秒的休眠时长内,程序已经运行完成,每个线程get到的a值都是 10 / 1 。
这个结果是我们不想的,我们通过python中提供的锁机制,某段代码只能单线程执行时,上锁,其他线程等待,直到释放锁后,其他线程再争锁,执行代码,释放锁,重复以上。
1.5 线程 加锁、解锁机制
可以利用locka = threading.Lock() 方法实现锁机制。通过执行 获得锁 locka.acquire(),通过 locka.release() 释放锁。
1 import threading 2 import time 3 locka = threading.Lock() 4 a = 0 5 def add(): 6 global a 7 try: 8 locka.acquire() # 获得锁 9 tmp = a + 1 # 等差 +1 10 time.sleep(0.2) # 延时0.2秒,模拟写入所需时间 11 a = tmp 12 finally: 13 locka.release() # 解放锁 14 print("%s adds a to 1:%d"%(threading.current_thread().getName(), a)) 15 16 threads = [threading.Thread(name = 't%d' %(i,), target=add) for i in range(10)] 17 [t.start() for t in threads]
可知,实现的我们想要的结果,但是这已经是单线程顺序执行了,已经失去多线程的价值,并且还带来了因为线程创建开销,浪费时间的副作用。
程序中只有一把锁,通过 try...finally 还能确保不发生死锁。但是,当程序中启用多把锁,还是很容易发生死锁。
因此注意使用场合,避免死锁,是我们在使用多线程开发时需要注意的一些问题。
————————————————
版权声明:本文为CSDN博主「唐樽」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_44775255/article/details/120435611
标签:thread,python,threading,线程,print,import,my From: https://www.cnblogs.com/sunzhiqi/p/16742405.html