一、线程管理
在多线程编程中,线程管理是一个非常重要的部分。在Python中,线程可以通过Thread类进行创建和控制。
import threading
import time
def worker():
print("Worker start.")
time.sleep(5)
print("Worker end.")
t1 = threading.Thread(target=worker)
t1.start()
上面的代码通过Thread类创建了一个名叫t1的线程,并传入了worker函数作为线程的执行函数。执行t1.start()后,该线程就开始执行了。在这个例子中,worker函数是一个简单的模拟耗时操作的函数,执行5秒后就结束。当线程执行完成后,Python解释器并不会自动将其销毁,需要调用t1.join()方法等待线程执行完毕,或者调用t1.is_alive()方法判断线程是否还在执行。
二、线程控制
线程控制是多线程编程中的关键部分,可以通过一些方法对线程进行控制,比如等待线程执行完成、终止线程等。
1.等待线程执行完成
在多线程编程中,常见的需求就是等待所有子线程执行完成之后再进行后续操作,可以通过遍历所有线程来实现。
import threading
import time
def worker():
print("Worker start.")
time.sleep(5)
print("Worker end.")
threads = []
for i in range(5):
t = threading.Thread(target=worker)
t.start()
threads.append(t)
for t in threads:
t.join()
print("All workers done.")
上面的代码中,创建了5个线程并挂起,每个线程执行5秒后结束。在创建完所有线程之后,遍历所有线程并执行t.join()等待线程执行完毕。执行完毕后会打印出"All workers done."。
2.终止线程
终止线程是一种非常危险的操作,只有在必要时才应该使用。可以通过设置线程的stop标志位或者调用线程的terminate()方法来终止线程。
(1)设置stop标志位
可以通过设置线程的stop标志位,来令线程主动结束。
import threading
import time
class MyThread(threading.Thread):
def __init__(self):
super(MyThread, self).__init__()
self.stop = False
def run(self):
print("Thread start.")
while not self.stop:
print("Thread is running.")
time.sleep(1)
print("Thread end.")
def stop_thread(self):
self.stop = True
t = MyThread()
t.start()
time.sleep(5)
t.stop_thread()
上面的代码中,自定义了一个MyThread类,线程执行的代码在run方法中。run方法通过检查stop标志位来判断线程是否应该结束,并在需要时结束线程。当需要结束线程时,调用MyThread的stop_thread方法,将stop标志位设置为True即可。
(2)调用terminate()方法
还可以直接调用线程的terminate()方法来终止线程,但是该方法很危险,应该在必要时才使用。因为线程在执行过程中可能会持有锁或者其他资源,在线程被突然终止的情况下,可能会导致这些资源被永久占用。
import threading
import time
def worker():
print("Worker start.")
while True:
print("Worker is running.")
time.sleep(1)
t = threading.Thread(target=worker)
t.start()
time.sleep(5)
t.terminate() # 终止线程
三、线程同步
在多线程编程中,线程之间可能会存在一些共享资源,如果多个线程同时对这些资源进行读写,就可能导致数据不一致或者异常情况。为了解决这个问题,需要使用线程同步机制来协调多个线程的操作。
1.Lock对象
Lock对象可以用来协调多个线程对临界区的访问。临界区就是指多个线程都要访问的共享资源区域,需要在访问该区域之前获取锁,访问完毕后释放锁。
import threading
import time
class SharedResource:
def __init__(self):
self.lock = threading.Lock()
self.count = 0
def increment(self):
with self.lock:
self.count += 1
print("SharedResource: ", self.count)
def worker(resource):
for i in range(5):
resource.increment()
time.sleep(1)
resource = SharedResource()
threads = []
for i in range(3):
t = threading.Thread(target=worker, args=(resource,))
t.start()
threads.append(t)
for t in threads:
t.join()
print("All workers done.")
上面的代码中,自定义了一个SharedResource类,该类维护了一个共享计数器count。increment方法对计数器进行加1操作,并使用with锁语句获取锁,避免多个线程同时修改计数器。在worker函数中创建了3个线程,并让每个线程调用5次increment方法,每次调用前都会获取锁进行保护。执行完毕后打印"All workers done."。
2.Condition对象
Condition对象也可以用来协调多个线程的访问。与Lock对象不同的是,Condition对象可以在特定变量满足某些条件时,释放所有等待该条件的线程,也可以在某个条件被满足时唤醒所有等待的线程。
import threading
import time
class SharedResource:
def __init__(self):
self.lock = threading.Lock()
self.condition = threading.Condition(self.lock)
self.count = 0
def increment(self):
with self.lock:
self.count += 1
print("SharedResource: ", self.count)
if self.count >= 5:
self.condition.notify_all()
def wait(self):
with self.lock:
while self.count < 5:
self.condition.wait()
def worker(resource):
for i in range(5):
resource.increment()
time.sleep(1)
resource.wait()
resource = SharedResource()
threads = []
for i in range(3):
t = threading.Thread(target=worker, args=(resource,))
t.start()
threads.append(t)
for t in threads:
t.join()
print("All workers done.")
上面的代码中,SharedResource类中增加了wait方法,并在increment方法中增加了一个判断,当计数器达到5时,调用notify_all方法唤醒所有等待该条件的线程。在worker函数中,每个线程执行5次increment方法后,会调用wait方法等待条件满足。最后的打印"All workers done."会在所有线程都执行完毕并完成条件等待后打印。