python 线程

http://t.zoukankan.com/ldy-miss-p-8706318.html

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

 

posted @ 2022-09-29 17:35  寒风孤影,江湖故人  阅读(73)  评论(0编辑  收藏  举报