Python多线程编程(二)

来源:互联网 发布:礼品卡兑换系统源码 编辑:程序博客网 时间:2024/04/30 15:09

我在Python多线程编程(一) 这篇文章中记录了一下threading模块的常用方法和两种写run()函数的方法。这篇文章写一下自己遇到过的几个问题,通过实例重新理解下join()函数,以及多线程修改全局变量时的坑。

首先明确下下join()函数的作用:主线程A中创建了一个子线程B,并且在主线程中调用B.join()方法。那么主线程就会在调用B.join()这个地方等待,直到子线程B完成操作或者子线程B超时,主线程A才可以继续往下面执行其他语句

1. 每个线程操作一个全局变量进行累加,最后结果应该是什么?

  下面代码中用了10个线程去执行一个10000 次的for循环,以此累加COUNT 这个全局变量,我们COUNT值累加后会是10000吗?或者是其他的值?

脚本 1.py

[yantao@yantao thread]$ cat 1.py #/usr/bin/python#coding: utf-8import threadingCOUNT = 0class AddUp(threading.Thread):    def __init__(self):        threading.Thread.__init__(self)    def run(self):        global COUNT        for i in xrange(10000):            COUNT += 1        print 'Current result: ',COUNTif __name__ == '__main__':    for i in range(10):        thread = AddUp()        thread.start()        thread.join()    print 'COUNT: ',COUNT

运行结果如下:

[yantao@yantao thread]$ python 1.py Current result:  10000Current result:  20000Current result:  30000Current result:  40000Current result:  50000Current result:  60000Current result:  70000Current result:  80000Current result:  90000Current result:  100000COUNT:  100000

  最后的结果是100000,和“预期”结果相符合。但是,事实并不是这样的,我们的目的是10个线程并发累加得到COUNT的值1.py 脚本虽然在主线程中又产生了10个线程,但实际上这10个线程是串行的,并不是并行的!
  为什么呢?来分析下产生线程的代码:

if __name__ == '__main__':    for i in range(10):        thread = AddUp()        thread.start()        thread.join()    print 'COUNT: ',COUNT

我们观察到子线程thread在start()后,我们在主线程中立刻调用了thread线程的join()函数,以此来阻塞当前线程(主线程)。那么我们的主线程就会停留在join()函数这里,直到子线程返回结果后,主线程才会继续执行for循环产生新的线程,但是我们继续调用了新线程的join()方法,主线程会继续等待直到新的子线程返回结果才会继续执行。如此反复10次。从这个逻辑可以看出,这里并没有并发,只不过是用了10个线程分别循环10000次,做了主线程循环100000次就可以做到的事情。 那么如何做到并发了?只要对1.py稍作更改即可,如下2.py

脚本 2.py

#/usr/bin/python#coding: utf-8import threadingCOUNT = 0class AddUp(threading.Thread):    def __init__(self):        threading.Thread.__init__(self)    def run(self):        global COUNT                 for i in xrange(10000):            COUNT += 1if __name__ == '__main__':    threads = []    for i in range(10):        thread = AddUp()        #print thread.getName()        threads.append(thread)      #将所有子线程放在一个列表里面        thread.start()                       #线程执行后不阻塞主线程,继续执行for循环产生新的线程    for thread in threads:              #在此处阻塞主线程,直到所有子线程返回        thread.join()    print COUNT

多次运行程序看下结果:

[yantao@yantao thread]$ python 2.py 53359[yantao@yantao thread]$ python 2.py 47909[yantao@yantao thread]$ python 2.py 52725

  从结果看每次运行的并不一样,这说明这里确实是并发了,但是为什么值会不一样了?因为多个线程操作一个全局变量时,会发生资源抢占,变量不能按照预定的逻辑进行操作,比如我们这里得到得结果就不是100000.
  在使用多线程时,尽量避免操作全局变量,以免引发不必要得麻烦,如果非要用,应该做好锁机制。

0 0