Python 多线程编程实战:从创建到同步详解
本文详细解析 Python 多线程编程的核心概念与实现方法。内容涵盖使用 thread 模块、继承 Thread 类及直接指定 target 三种线程创建方式,深入讲解 Thread 对象的常用方法如 join、setDaemon 等。重点阐述利用 Lock、Condition 和 Event 对象实现线程同步与通信,通过代码示例演示如何处理竞态条件及线程间信号交互,帮助开发者掌握并发编程的关键技术。
Python 多线程编程实战详解
一、线程基础概念
1. 创建线程的三种主要方式
Python 中的 thread 模块提供了 start_new_thread 函数,用于创建新的线程。该函数在成功创建线程后,允许对线程进行进一步的操作。其函数原型如下:
start_new_thread(function,atgs[,kwargs])
该函数的参数含义如下:
function:指定在线程中执行的函数名称。 args:以元组形式传递的参数列表。 kwargs:可选参数,以字典形式指定参数。
方法一:利用 thread 模块中的 start_new_thread 函数直接创建新线程。
>>> import thread
>>> def run(n):
for i in range(n):
print i
>>> thread.start_new_thread(run,(4,)) #注意第二个参数一定要是元组的形式
53840
1
>>>
2
3
KeyboardInterrupt
>>> thread.start_new_thread(run,(2,))
17840
1
>>>
thread.start_new_thread(run,(),{'n':4})
39720
1
>>>
2
3
thread.start_new_thread(run,(),{'n':3})
32480
1
>>>
2
方法二:通过继承 threading.Thread 类来创建自定义线程类。
>>> import threading
>>> class mythread(threading.Thread):
def __init__(self,num):
threading.Thread.__init__(self)
self.num = num
def run(self): #重载run方法
print 'I am', self.num
>>> t1 = mythread(1)
>>> t2 = mythread(2)
>>> t3 = mythread(3)
>>> t1.start() #运行线程t1
I am
>>> 1
t2.start()
I am
>>> 2
t3.start()
I am
>>> 3
方法三:直接使用 threading.Thread 类,并通过 target 参数指定在线程中运行的函数。
import threading
>>> def run(x,y):
for i in range(x,y):
print i
>>> t1 = threading.Thread(target=run,args=(15,20)) #直接使用Thread附加函数args为函数参数
>>> t1.start()
15
>>>
16
17
18
19
二、Thread 对象的常用方法
1. isAlive 方法:
>>> import threading
>>> import time
>>> class mythread(threading.Thread):
def __init__(self,id):
threading.Thread.__init__(self)
self.id = id
def run(self):
time.sleep(5) #休眠5秒
print self.id
>>> t = mythread(1)
>>> def func():
t.start()
print t.isAlive() #打印线程状态
>>> func()
True
>>> 1
2. join 方法:
原型:join([timeout])
timeout:可选参数,指定线程运行的最长时间。
import threading
>>> import time #导入time模块
>>> class Mythread(threading.Thread):
def __init__(self,id):
threading.Thread.__init__(self)
self.id = id
def run(self):
x = 0
time.sleep(20)
print self.id
>>> def func():
t.start()
for i in range(5):
print i
>>> t = Mythread(2)
>>> func()
0
1
2
3
4
>>> 2
def func():
t.start()
t.join()
for i in range(5):
print i
>>> t = Mythread(3)
>>> func()
3
0
1
2
3
4
>>>
3. 线程命名:
>>> import threading
>>> class mythread(threading.Thread):
def __init__(self,threadname):
threading.Thread.__init__(self,name=threadname)
def run(self):
print self.getName()
>>>
>>> t1 = mythread('t1')
>>> t1.start()
t1
>>>
4. setDaemon 方法
在脚本运行过程中存在一个主线程。如果主线程创建了一个子线程,当主线程退出时,会检查子线程是否已完成。如果子线程尚未完成,主线程将等待子线程执行完毕后再退出。
若希望主线程退出时,无论子线程是否完成都立即随主线程退出,可以使用 Thread 对象的 setDaemon 方法进行设置。
三、线程同步机制
1. 简单的线程同步实现
使用 Thread 对象的 Lock 和 RLock 可以实现简单的线程同步。对于每次仅允许一个线程操作的数据,可将操作过程封装在 acquire 方法和 release 方法之间。例如:
# -*- coding:utf-8 -*-
import threading
import time
class mythread(threading.Thread):
def __init__(self,threadname):
threading.Thread.__init__(self,name = threadname)
def run(self):
global x #设置全局变量
# lock.acquire() #调用lock的acquire方法
for i in range(3):
x = x + 1
time.sleep(2)
print x
# lock.release() #调用lock的release方法
#lock = threading.RLock() #生成Rlock对象
t1 = []
for i in range(10):
t = mythread(str(i))
t1.append(t)
x = 0 #将全局变量的值设为0
for i in t1:
i.start()
E:/study/<a href="http://lib.csdn.net/base/python" rel="external nofollow" class='replace_word' title="Python知识库" target='_blank' style='color:#df3434; font-weight:bold;'>Python</a>/workspace>xianchengtongbu.py
3
6
9
12
15
18
21
24
27
30
如果删除代码中的 lock.acquire()、lock.release() 以及 lock = threading.Lock() 后保存并运行脚本,输出结果将是 10 个 30。这里的 30 是变量 x 的最终值。由于 x 是全局变量,每个线程对其操作后进入休眠状态,在线程休眠期间,Python 解释器会执行其他线程,导致 x 的值增加。当所有线程休眠结束后,x 的值已被所有线程修改为 30,因此输出全部为 30。
2. 使用条件变量保持线程同步
Python 的 Condition 对象提供了对复杂线程同步的支持。使用 Condition 对象可以在特定事件触发后才处理数据。Condition 对象除了具备 acquire 和 release 方法外,还包含 wait、notify 和 notifyAll 等方法,用于处理条件逻辑。
# -*- coding:utf-8 -*-
import threading
class Producer(threading.Thread):
def __init__(self,threadname):
threading.Thread.__init__(self,name = threadname)
def run(self):
global x
con.acquire()
if x == 1000000:
con.wait()
# pass
else:
for i in range(1000000):
x = x + 1
con.notify()
print x
con.release()
class Consumer(threading.Thread):
def __init__(self,threadname):
threading.Thread.__init__(self,name = threadname)
def run(self):
global x
con.acquire()
if x == 0:
con.wait()
#pass
else:
for i in range(1000000):
x = x - 1
con.notify()
print x
con.release()
con = threading.Condition()
x = 0
p = Producer('Producer')
c = Consumer('Consumer')
p.start()
c.start()
p.join()
c.join()
print x
E:/study/python/workspace>xianchengtongbu2.py
1000000
0
0
线程间通信:
Event 对象用于实现线程间的相互通信。它提供了设置信号、清除信号以及等待等功能,用于实现线程间的同步通信。
1. 设置信号:Event 对象调用 set() 方法后,isSet() 方法返回 True。 2. 清除信号:使用 Event 对象的 clear() 方法后,isSet() 方法返回 False。 3. 等待:当 Event 对象的内部信号标志为 False 时,wait() 方法会一直等待,直到信号变为 True 时才返回。还可以向 wait 传递参数,设定最长的等待时间。
# -*- coding:utf-8 -*-
import threading
class mythread(threading.Thread):
def __init__(self,threadname):
threading.Thread.__init__(self,name = threadname)
def run(self):
global event
if event.isSet():
event.clear()
event.wait() #当event被标记时才返回
print self.getName()
else:
print self.getName()
event.set()
event = threading.Event()
event.set()
t1 = []
for i in range(10):
t = mythread(str(i))
t1.append(t)
for i in t1:
i.start()
如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









