Python多线程学习-叁-threading

本文详细介绍了Python多线程并发技术,包括Lock、RLock、Condition、Event、Semaphore和BoundedSemaphore等类的使用,并通过实例展示了它们在不同场景下的应用。此外,还对比了Thread、Timer等常用类的功能,帮助读者全面掌握Python并发编程的基础与实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

Python 多线程threading学习

 

 

上一节学习了threading.Lockthreading.RLockthreading.Condition,如果全部理解的话,同步方面的知识应该不错的了。threading还有一个Event类,这个类也是用来同步的,不过这个类提供线程之间的模型也最为简单,了解即可。其实对于熟悉Condition的来说,Event就不是特别必要了。不过有时候线程的事情未必会需要Condition,能用个轻量级的Event解决就不必使用牛刀了。

 

 

Event的说明如下:

 

This is one of the simplest mechanisms for communication between threads: one thread signals an event and other threads wait for it.

An event object manages an internal flag that can be set to true with the set() method and reset to false with the clear() method. The wait() method blocks until the flag is true.

 

 

这个看说明就知道什么意思。只是把锁包装一下,添加wait方法。算是锁最近单的实现了。

 

 

唯一需要注意的是wait方法的解释:

 

wait([timeout])
           Block until the internal flag is true. If the internal flag is true on entry, return immediately. Otherwise, block until another thread calls set() to set the flag to true, or until the optional timeout occurs.

 

 

这个wait是个阻塞操作,这点使用时要注意。

 

 

#encoding=gbk
import threading  
import time  
  
class MyThread(threading.Thread):  
    def __init__(self, signal):  
        threading.Thread.__init__(self)  
        self.singal = signal  
          
    def run(self):  
        print "I am %s,I will sleep ..."%self.name  
        self.singal.wait()  
        print "I am %s, I awake..." %self.name  
          
if __name__ == "__main__":  
    singal = threading.Event()  
    for t in range(0, 3):  
        thread = MyThread(singal)  
        thread.start()  
    print "main thread sleep 3 seconds... "  
    time.sleep(3)  
    singal.set() 
 

 

后面还有一个Semaphore类,这个类的说明如下:

 

This is one of the oldest synchronization primitives in the history of computer science, invented by the early Dutch computer scientist Edsger W. Dijkstra (he used P() and V() instead of acquire() and release()).

A semaphore manages an internal counter which is decremented by each acquire() call and incremented by each release() call. The counter can never go below zero; when acquire() finds that it is zero, it blocks, waiting until some other thread calls release().
 

 

按照解释,semaphore管理一个内置的计数器,调用acquire方法是-1,调用release方法时+1,负责某个资源可以使用的线程数。实际上是控制在某个资源上,同时可以上几把锁,有几个线程来访问。semephore的构造方法能够选择选择内置计数器的初始值,默认初始值为1

这个结合ConditionEvent的思路就清楚了,实际上是在锁上添加了限制。

 

 

#encoding=gbk

import threading
import time

class semaphore_thread(threading.Thread):
  def __init__(self,semaphore):
    threading.Thread.__init__(self);
    self.semaphore = semaphore

  def run(self):
    if semaphore.acquire():
      print "%s get semaphore" %(threading.currentThread().getName())
      time.sleep(3)
      semaphore.release()
      print "%s release semaphore" %(threading.currentThread().getName())

if __name__ == "__main__":
  semaphore = threading.Semaphore(3)
  for i in range(10):
    t=semaphore_thread(semaphore)
    t.start()
 

根据输出结果,可以看到在同一个时刻,最多只能有三个线程获得锁运行,其它线程都处于等待状态,实现资源的控制。

 

 

另外threading模块还有个BounderSemaphore,这个是个Factory function,直接返回一个bounded semaphore,这个BoundedSemaphore能够确保当前值不会大于初始值,否则ValueError会被抛出来。其实这个BoundedSemaphore就是Semaphore添加边界检查的功能,不再举例了。

 

 

threading包到这里就告一段落了,回顾一下,我们学习了如下类:

 

 

threading.Thread
threading.Timer
threading.Lock
threading.RLock
threading.Condition
threading.Event
threading.Semaphore
threading.BoundedSemaphore
 

 

这些类的熟练使用能够保证你准确安全的使用并发多线程。

不过学习完多线程就Ok了?No,这些线程的使用实际上是单个Processor流转处理各个Thread,这个确实很快,至少我们感觉不出来。

不过对于多Processor的处理,使用线程模型只是利用了有限的Processor,同样Python提供了multiprocessing包来提升多核的处理能力。这个算是threading的进阶,有时间的话会分析下multiprocessing的处理过程。

 

 

 

 

 

Python中,多线程编程是通过`threading`模块实现的,该模块提供了创建和管理线程的工具。多线程允许程序同时执行多个任务,从而提高响应能力和资源利用率。然而,由于Python的全局解释器锁(GIL)的存在,多线程在CPU密集型任务中并不能真正实现并行计算,但在I/O密集型任务中仍能显著提升性能。 ### 创建和启动线程 使用`threading.Thread`类可以创建线程对象,并通过调用其`start()`方法启动线程。以下是一个简单的示例: ```python import threading def worker(): print("Worker thread is running") # 创建线程对象 thread = threading.Thread(target=worker) # 启动线程 thread.start() # 等待线程结束 thread.join() ``` ### 线程同步 在多线程环境中,多个线程可能会同时访问共享资源,导致数据不一致或竞态条件。为了解决这个问题,可以使用线程同步机制,如锁(Lock)、条件变量(Condition)和信号量(Semaphore)等。例如,使用`threading.Lock`来确保同一时间只有一个线程访问共享资源: ```python import threading # 创建锁对象 lock = threading.Lock() shared_resource = 0 def increment(): global shared_resource for _ in range(100000): lock.acquire() shared_resource += 1 lock.release() # 创建多个线程 threads = [threading.Thread(target=increment) for _ in range(4)] for thread in threads: thread.start() for thread in threads: thread.join() print(f"Final value of shared resource: {shared_resource}") ``` ### 线程间通信 除了锁之外,还可以使用`threading.Condition`来进行线程间的协调。条件变量允许一个或多个线程等待某个条件成立,然后被通知继续执行。以下是一个使用条件变量的示例: ```python import threading condition = threading.Condition() resource_available = False def consumer(): with condition: while not resource_available: condition.wait() # 使用资源 print("Resource is being used") def producer(): global resource_available with condition: resource_available = True condition.notify_all() # 创建并启动线程 consumer_thread = threading.Thread(target=consumer) producer_thread = threading.Thread(target=producer) consumer_thread.start() producer_thread.start() consumer_thread.join() producer_thread.join() ``` ### 多线程与性能优化 尽管多线程在I/O密集型任务中非常有效,但在CPU密集型任务中,由于GIL的限制,多线程并不能充分利用多核处理器的优势。对于这类任务,推荐使用`multiprocessing`模块来实现真正的并行计算。 在设计多线程程序时,还需要注意以下几点: - **避免死锁**:确保每个线程获取锁的顺序一致,以防止死锁。 - **合理分配线程数量**:过多的线程会导致上下文切换开销增加,反而降低性能。 - **使用线程池**:可以使用`concurrent.futures.ThreadPoolExecutor`来简化线程管理,提高效率。 ### 示例:多线程下载文件 下面是一个使用多线程进行文件下载的示例,展示了如何并发地执行I/O密集型任务: ```python import threading import requests def download_file(url, filename): with requests.get(url, stream=True) as r: r.raise_for_status() with open(filename, 'wb') as f: for chunk in r.iter_content(chunk_size=8192): if chunk: f.write(chunk) print(f"{filename} downloaded") urls = [ "https://example.com/file1.txt", "https://example.com/file2.txt", "https://example.com/file3.txt" ] filenames = ["file1.txt", "file2.txt", "file3.txt"] threads = [] for url, filename in zip(urls, filenames): thread = threading.Thread(target=download_file, args=(url, filename)) threads.append(thread) thread.start() for thread in threads: thread.join() ``` 通过上述方法,可以在Python中有效地使用多线程编程[^1]。对于更复杂的并发需求,还可以考虑使用高级库如`asyncio`来进行异步编程,或者使用`concurrent.futures`模块提供的高级接口来简化并发任务的管理[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值