`
crazier9527
  • 浏览: 1013797 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Python多线程 简明例子

阅读更多

 综述

 
  多线程是程序设计中的一个重要方面,尤其是在服务器Deamon程序方面。无论何种系统,线程调度的开销都比传统的进程要快得多。
  Python可以方便地支持多线程。可以快速创建线程、互斥锁、信号量等等元素,支持线程读写同步互斥。美中不足的是,Python的运行在Python 虚拟机上,创建的多线程可能是虚拟的线程,需要由Python虚拟机来轮询调度,这大大降低了Python多线程的可用性。希望高版本的Python可以解决这个问题,发挥多CPU的最大效率。
  网上有些朋友说要获得真正多CPU的好处,有两种方法:
  1.可以创建多个进程而不是线程,进程数和cpu一样多。
  2.使用Jython 或 IronPython,可以得到真正的多线程。
 
  闲话少说,下面看看Python如何建立线程
 
  Python线程创建
 
  使用threading模块的 Thread类
  类接口如下
 
class Thread( group=None, taget=None, name=None, args=(), kwargs={})
 
  需要关注的参数是target和args. target 是需要子线程运行的目标函数,args是函数的参数,以tuple的形式传递。
  以下代码创建一个指向函数worker 的子线程
def worker(a_tid,a_account):
    …

 

th = threading.Thread(target=worker,args=(i,acc) ) ;

 
  启动这个线程
th.start()
 
  等待线程返回
threading.Thread.join(th)
或者th.join()
 
  如果你可以对要处理的数据进行很好的划分,而且线程之间无须通信,那么你可以使用:创建=》运行=》回收的方式编写你的多线程程序。但是如果线程之间需要访问共同的对象,则需要引入互斥锁或者信号量对资源进行互斥访问。
 
 下面讲讲如何创建互斥锁
创建锁
g_mutex = threading.Lock()

 

….
使用锁
    for … :
        #锁定,从下一句代码到释放前互斥访问
        g_mutex.acquire()
        a_account.deposite(1)
        #释放
        g_mutex.release()

 
  最后,模拟一个公交地铁IC卡缴车费的多线程程序
  有10个读卡器,每个读卡器收费器每次扣除用户一块钱进入总账中,每读卡器每天一共被刷10000000次。账户原有100块。所以最后的总账应该为10000100。先不使用互斥锁来进行锁定(注释掉了锁定代码),看看后果如何。
 
import time,datetime
import threading

def worker(a_tid,a_account):
    global g_mutex
    print “Str ” , a_tid, datetime.datetime.now()
    for i in range(1000000):
        #g_mutex.acquire()
        a_account.deposite(1)
        #g_mutex.release()

    print “End ” , a_tid , datetime.datetime.now()
    
class Account:
    def __init__ (self, a_base ):
        self.m_amount=a_base
    def deposite(self,a_amount):
        self.m_amount+=a_amount
    def withdraw(self,a_amount):
        self.m_amount-=a_amount    
        
if __name__ == “__main__”:
    global g_mutex
    count = 0
    dstart = datetime.datetime.now()
    print “Main Thread Start At: ” , dstart

    #init thread_pool
    thread_pool = []
    #init mutex
    g_mutex = threading.Lock()
    # init thread items
    acc = Account(100)
    for i in range(10):
        th = threading.Thread(target=worker,args=(i,acc) ) ;
        thread_pool.append(th)
        
    # start threads one by one        
    for i in range(10):
        thread_pool[i].start()
    
    #collect all threads
    for i in range(10):
        threading.Thread.join(thread_pool[i])
    dend = datetime.datetime.now()
    print “count=”,acc.m_amount
    print “Main Thread End at: ” ,dend , ” time span ” , dend-dstart;

 
  注意,先不用互斥锁进行临界段访问控制,运行结果如下:
 
Main Thread Start At:    2009-01-13 00:17:55.296000
Str    0 2009-01-13 00:17:55.312000
Str    1 2009-01-13 00:17:55.453000
Str    2 2009-01-13 00:17:55.484000
Str    3 2009-01-13 00:17:55.531000
Str    4 2009-01-13 00:17:55.562000
Str    5 2009-01-13 00:17:55.609000
Str    6 2009-01-13 00:17:55.640000
Str    7 2009-01-13 00:17:55.687000
Str    8 2009-01-13 00:17:55.718000
Str    9 2009-01-13 00:17:55.781000
End    0 2009-01-13 00:18:06.250000
End    1 2009-01-13 00:18:07.500000
End    4 2009-01-13 00:18:07.531000
End    2 2009-01-13 00:18:07.562000
End    3 2009-01-13 00:18:07.593000
End    9 2009-01-13 00:18:07.609000
End    7 2009-01-13 00:18:07.640000
End    8 2009-01-13 00:18:07.671000
End    5 2009-01-13 00:18:07.687000
End    6 2009-01-13 00:18:07.718000
count= 3434612
Main Thread End at:    2009-01-13 00:18:07.718000    time span    0:00:12.422000
 
  从结果看到,程序确实是多线程运行的。但是由于没有对对象Account进行互斥访问,所以结果是错误的,只有3434612,比原预计少了很多。
 
  把上面阴影部分代码的注释打开,运行结果如下
Main Thread Start At:    2009-01-13 00:26:12.156000
Str    0 2009-01-13 00:26:12.156000
Str    1 2009-01-13 00:26:12.390000
Str    2 2009-01-13 00:26:12.437000
Str    3 2009-01-13 00:26:12.468000
Str    4 2009-01-13 00:26:12.515000
Str    5 2009-01-13 00:26:12.562000
Str    6 2009-01-13 00:26:12.593000
Str    7 2009-01-13 00:26:12.640000
Str    8 2009-01-13 00:26:12.671000
Str    9 2009-01-13 00:26:12.718000
End    0 2009-01-13 00:27:01.781000
End    1 2009-01-13 00:27:05.890000
End    5 2009-01-13 00:27:06.046000
End    7 2009-01-13 00:27:06.078000
End    4 2009-01-13 00:27:06.109000
End    2 2009-01-13 00:27:06.140000
End    6 2009-01-13 00:27:06.156000
End    8 2009-01-13 00:27:06.187000
End    3 2009-01-13 00:27:06.203000
End    9 2009-01-13 00:27:06.234000
count= 10000100
Main Thread End at:    2009-01-13 00:27:06.234000    time span    0:00:54.078000
 
  这次可以看到,结果正确了。运行时间比不进行互斥多了很多,需要花54秒才能运行(我机器烂,没钱更新,呵呵),不过这也是同步的代价,没办法。
分享到:
评论
1 楼 greatghoul 2011-02-01  
我尝试用线程ping一个网段,经常输出的结果都是错乱的,看了你的文章后,后来在输出的部分加上了锁,就整齐正确了。

相关推荐

    python多线程同步之文件读写控制

    在Python编程中,多线程同步对于文件读写控制至关重要,因为如果不加以控制,多个线程同时访问同一文件可能会导致数据不一致或者错误。这里我们将深入探讨如何在Python中使用多线程同步来确保文件读写的安全性。 ...

    Python 多线程编程实例

    Python 多线程编程实例,一个综合示例

    基于Linux的python多线程爬虫程序设计.pdf

    本文提出了一种基于Linux平台和Python语言的多线程微博爬虫程序设计方法,旨在高效率、高并发地获取微博数据,并将其结构化存储。 首先,我们应当明确什么是网络爬虫。网络爬虫,也被称为Web爬虫或者网络蜘蛛,是一...

    python 多线程实现多个网址的多次快速访问

    在Python编程中,多线程是一种并发执行任务的机制,尤其在处理I/O密集型任务如网络请求时,能够显著提高程序效率。本教程将详细讲解如何使用Python的多线程来实现对多个网址的快速访问,并记录访问结果。 首先,...

    python多线程爬虫爬取电影天堂资源

    Python多线程爬虫爬取电影天堂资源是一个实用且具有挑战的项目。以下是对该项目的详细说明: 1. 项目概述: 该项目旨在使用Python编写一个多线程爬虫程序,从电影天堂网站上爬取电影资源信息,包括电影名称、年份、类型...

    python多线程压测demo

    python多线程压测demo

    10个线程的Python多线程爬虫(采集新浪数据).rar

    一个Python多线程爬虫,在工作时,开10个线程来抓取新浪网页的数据,抓取并保存页面, 并且根据deep返回页面链接,根据key确定是否保存该页面,其中:  deep == 0时,是抓取的最后一层深度,即只抓取并保存页面,不...

    python多线程Python多线程学习Python中的线程使用

    python,python多线程Python多线程学习Python中的线程使用python多线程Python多线程学习Python中的线程使用

    探寻python多线程ctrl+c退出问题解决方案

    经常会遇到下述问题:很多io busy的应用采取多线程的方式来解决,但这时候会发现python命令行不响应ctrl-c 了,而对应的java代码则没有问题: 复制代码 代码如下: public class Test {   public static void main...

    python多线程定时器

    在Python编程中,多线程和定时器是两个非常重要的概念。多线程允许程序同时执行多个任务,而定时器则能确保程序在特定时间点或以特定间隔执行某些操作。这里我们将深入探讨如何利用Python的`threading`模块来实现多...

    python 多线程脚本

    python 多线程封装脚本,可以直接拿来当lib导入使用。

    python多线程,断点续传下载程序

    python多线程,断点续传下载程序,功能比较简单,可以进行二次开发。实现更好用的 功能。

    python多线程 实例 注释详解

    python 多线程 实例 注释详解

    Python多线程超大日志文件解析转储写入mysql/postgresql

    Python多线程超大日志文件解析转储,实现几十G超大文件并发处理。 实现功能如下: 1.多线程分块解析某超大日志文件,实现超大文件多线程分块处理 2.多线程写入数据到数据库postgresql/mysql 3.线程之间通过队列queue...

    Python多线程编程

    Python多线程编程文档说明 多进程编程 一、 multiprocessing 模块 1. multiprocessing 模块提供了多进程编程的能力 它的API非常类似于 threading 模块,但是也提供了一些threading 模块不具有的能力 相比于线程,它...

    python多线程基础框架例子讲解视频

    python多线程基础框架例子讲解视频 今天给网友做一个关于python多线程的教程 也顺便解决网友提到的问题 这只是一个最简单的多线程例子。 在这个例子中并不能保证线程安全

    Python多线程Socket程序例子

    在Python编程中,多线程和Socket通信是两个重要的概念,它们经常被结合使用以实现高效、并发的网络服务。本篇文章将详细讲解如何在Python中编写一个多线程的Socket程序,通过分析提供的代码示例`...

    使用python多线程异步提高模型部署到rk3588NPU使用率-python源码+项目使用说明.zip

    使用python多线程异步提高模型部署到rk3588NPU使用率_python源码+项目使用说明.zip 【项目资源说明】 使用多线程异步操作rknn模型, 提高rk3588/rk3588s的NPU使用率, 进而提高推理帧数(rk3568之类修改后应该也能使用,...

    浅析Python多线程与多进程的使用

    在多线程编程中,我们需要注意全局解释器锁(GIL),它是Python解释器为了保证线程安全而引入的一个机制,但同时也限制了多线程在CPU密集型任务中的性能,因为GIL使得Python在同一时刻只能有一个线程在执行。...

    单线程与多线程python爬虫地图瓦片源码

    本文将深入探讨“单线程与多线程Python爬虫地图瓦片源码”的相关知识点。 首先,我们需要理解“线程”这一概念。线程是程序执行的最小单元,每个线程负责执行特定的任务。在单线程环境中,程序按顺序执行,一次只能...

Global site tag (gtag.js) - Google Analytics