首页 > 编程语言 >python 线程

python 线程

时间:2022-09-29 17:46:15浏览次数:75  
标签:thread python threading 线程 print import my

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

相关文章

  • python使用win32api进行后台窗口的部分截图函数
    defwindow_capture_beat(hwnd,stayx:int,endx:int,stay:int,endy:int):hwndDC=win32gui.GetWindowDC(hwnd)mfcDC=win32ui.CreateDCFromHandle(hwndDC)......
  • python 监控键盘事件
    frompynputimportkeyboard#按下后执行defon_press(key):try:ifkey==keyboard.KeyCode.from_char('enter'):passelifkey......
  • python5种线程锁
    # 线程安全线程安全是多线程或多进程编程中的一个概念,在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且正确的执行,不会......
  • python 生成伪随机数函数 random
    """random函数:出一个伪随机数具体怎么做?一般我们会考虑先查找python官方自带的文档在IDLE的右上角点击HELP-->PythonDoc(F1)-->点击左上角的索引-->输入我们要......
  • python dis模块
    python中的dis模块可以查看一句python代码的cpu运行轨迹,也就是cpu指令,如果只是读取数据时,如读取一个函数,此时数据是安全的,因为没有涉及任何修改,当改数据时,可能会涉及数据不......
  • 分分钟学会一门语言之Python篇
    github:原文#Singlelinecommentsstartwithahash.#单行注释由一个井号开头。"""Multilinestringscanbewrittenusingthree"'s,andareoftenusedas......
  • Python实现队列,堆栈
    一、队列classQueue:def__init__(self,size):self.size=sizeself.front=-1self.rear=-1self.queue=[]def......
  • python argparse使用及常用环境
    简介argparse是python中用来方便获取命令行参数的模块,也可以很方便的做一个简单的命令行参数的设定,例如ls-h等后面加参数的情况,可以自己创建一个支持命令行参数的命令......
  • python之第三方库pycurl库:PycURl是一个C语言写的libcurl的python绑定库。libcurl 是一
    ​​https://zhuanlan.zhihu.com/p/163173013​​​去期待陌生,去拥抱惊喜。......
  • Python元组常用方法 || 元组和列表的区别
    Python元组常用方法前言①通过()创建元组。小括号可以省略。a=(10,20,30)或者a=10,20,30【注意】:如果元组只有一个元素,则必须后面加逗号。这是因为python解释器会把 ......