免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2082 | 回复: 0
打印 上一主题 下一主题

Python多线程 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-03-23 13:48 |只看该作者 |倒序浏览

Python的并行开发有两种方式:fork和thread(线程)。thread比fork更轻量级,具有更好运行效率和可移植性,在需要进行并行操作的场合首推thread。
python标准库内置一个thread模块,该模块提供一个轻便简易的多线程编程接口,可以无需任何修改就能够运行在Win、Solaris、Linux等操作系统上。浏览一下thread模块:
import thread
dir(thread)
看到
['LockType', '__doc__', '__name__', '_local', 'allocate', 'allocate_lock', 'error', 'exit', 'exit_thread', 'get_ident', 'interrupt_main', 'stack_size', 'start_new', 'start_new_thread']
创建线程是我们的首要任务,我们将要用到的是start_new和start_new_thread方法,我们推荐start_new_thread,因为start_new已经是陈旧的版本。下面的代码展示了如何创建线程:
import thread
def childthread(threadid):
        print 'I am child thread',threadid
def parentthread():
        i=0
        while 1:
                  i+=1
                  thread.start_new_thread(childthread,(i,))
                  if raw_input()=='q':break
parentthread()
运行该程序会看到如下效果:
I am child thread 1
I am child thread 2
I am child thread 3
q
每次按下回车,屏幕上就会出现一行来自start_new_thread所创建的线程的信息,知道我们输入q按回车为止。
可见thread模块通过start_new_thread给我们提供一个基于函数的线程创建接口。start_new_thread方法有两个参数,第一个参数是我们预定义的函数(这里是childthread),也就是我们想要创建的线程体;第二个参数是一个tuple(元组),罗列线程体的函数的所有参数,为什么要用一个tuple呢?python很具灵活性,因为不管线程体有多少个参数,通过一个tuple我们就可以传递足够的参数,这里我么传递一个(i,)的tuple,表示只有一个参数。
Python中,我们可以使用N个线程同时访问该进程的内存空间,这是线程固有的特点。下面我们尝试做到这一点。
import thread
i=0
def doit(ind):
         global i
         temp=i
         i=temp+1
         print "i=%d" % i
for ind in range(1000):
         thread.start_new_thread(doit,(ind,))
raw_input()
运行代码,我们看到好奇怪的现象:

程序期待的结果是依次打印出从1到1000的值,而我们发现部分数值并没有被打印出来,而部分数值却重复打印了。原因很简单,试想现在有A、B两个线程同时访问i,执行顺序如下,假设现在i=100:
A: temp=100
B: temp=100
A: i=temp+1=100+1=101
A: 打印i=101
B: i=temp+1=100+1=101
B: 打印i=101
很显然,我们得到了两条i=101的结果,这就是为什么会出现上面的现象。原因是各个线程之间对变量的访问没有一个粒子性,就是没有实现当A线程访问变量i的时候,B线程应该等待A线程处理完后再访问i。这个就是线程同步的问题。
对于这个问题,python同样给我提供一个很轻便的接口去解决,就是锁(lock)。当一个线程申请一个锁以后,其他线程如果要申请锁,必须要等待这个锁被释放以后才能得到,从而实现线程的互相等待。下面尝试通过锁解决这个问题:
import thread
i=0
def doit(ind):
       global i
       global mutex
       mutex.acquire()
       temp=i
       i=temp+1
       print "i=%d" % i
       mutex.release()
mutex=thread.allocate_lock()
for ind in range(1000):
       thread.start_new_thread(doit,(ind,))
raw_input()
运行程序,现在我们可以看到i从1到1000很正常的打印出来了。我们把temp=i和i=temp+1语句放在申请锁和释放锁中间,就可以防止多个线程同时执行这两段代码。


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/89795/showart_1875957.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP