Python threading的使用方法解析
什么是线程?
线程是指在单个程序内执行的一系列并发执行的控制流,每个线程都有自己的代码执行路径、程序计数器和栈。在一个进程内,多个线程可共享同一内存地址空间。
基本语法
在Python中,使用threading
库可方便地实现线程功能。
创建线程:
import threading
def my_thread():
print("this is my thread")
if __name__ == "__main__":
t = threading.Thread(target=my_thread)
启动线程:
t.start()
阻塞主线程直到所有子线程完成:
t.join()
结束线程:
threading.Thread._stop()
线程同步
在线程之间共享变量时,可能会发生数据竞争问题。为避免此问题,可以使用线程同步。
互斥锁(Mutex)
互斥锁可用来保护共享变量不被多个线程同时修改。
mutex = threading.Lock()
mutex.acquire()
# access shared data
mutex.release()
信号量(Semaphore)
信号量的作用是将并行性降级为串行性。它用来控制同时访问某个资源的用户数。
semaphore = threading.Semaphore(3)
semaphore.acquire()
# access shared data
semaphore.release()
条件(Condition)
条件是多线程编程中最常见的同步原语之一。每个条件都与一个锁对象关联,同时具有一个等待列表。当线程调用条件的等待方法之一时,它会将线程放置到列表中并释放锁。当前等待列表上的线程,在条件或者超时时,会重新获取锁并继续执行。
condition = threading.Condition()
condition.acquire()
# access shared data
condition.notify()
condition.release()
示例说明
示例1: 使用互斥锁
import threading
class Counter:
def __init__(self):
self.value = 0
self.mutex = threading.Lock()
def increment(self):
self.mutex.acquire()
self.value += 1
self.mutex.release()
def update(counter):
for i in range(10000):
counter.increment()
def main():
counter = Counter()
threads = []
for i in range(10):
threads.append(threading.Thread(target=update, args=(counter,)))
threads[-1].start()
for t in threads:
t.join()
print(counter.value)
main()
示例2: 使用条件同步
import threading
class Worker:
def __init__(self):
self.queue = []
self.condition = threading.Condition()
def produce(self):
with self.condition:
while len(self.queue) > 0:
self.condition.wait()
print('Producing Item')
self.queue.append(1)
self.condition.notify_all()
def consume(self):
with self.condition:
while len(self.queue) == 0:
self.condition.wait()
print('Consuming Item')
self.queue.pop(0)
self.condition.notify_all()
def worker_thread(worker, is_producer):
for i in range(10):
if is_producer:
worker.produce()
else:
worker.consume()
def main():
worker = Worker()
threads = []
threads.append(threading.Thread(target=worker_thread, args=(worker, True)))
threads.append(threading.Thread(target=worker_thread, args=(worker, False)))
for t in threads:
t.start()
for t in threads:
t.join()
main()
以上两个示例展示了线程同步中的互斥锁和条件同步的用法。在示例1中,组合使用互斥锁和计数器,保证了多个线程修改计数器时不会出现数据竞争问题。在示例2中,演示了生产者消费者模型中的条件同步。多个线程共同修改队列时,使用条件同步方式保证生产者在队列为空时才能生产,消费者在队列非空时才能消费,避免线程安全问题的同时提高了程序的效率。