首页 > 代码库 > Python中的多进程与多线程(二)

Python中的多进程与多线程(二)

  在上一章中,学习了Python多进程编程的一些基本方法:使用跨平台多进程模块multiprocessing提供的Process、Pool、Queue、Lock、Pipe等类,实现子进程创建、进程池(批量创建子进程并管理子进程数量上限)以及进程间通信。这一章学习下Python下的多线程编程方法。

一、threading

线程是操作系统执行任务的最小单元。Python标准库中提供了threading模块,对多线程编程提供了很便捷的支持。

下面是使用threading实现多线程的代码:

 1 #!/usr/bin/python
 2 # -*- coding: utf-8 -*
 3 __author__ = zni.feng
 4 import  sys
 5 reload (sys)
 6 sys.setdefaultencoding(utf-8)
 7 
 8 import threading, time
 9 
10 def test(index):
11     print time.strftime(%Y-%m-%d %H:%M:%S,time.localtime(time.time()))
12     print thread %s starts. % threading.current_thread().name
13     print the index is %d % index
14     time.sleep(3)
15     print time.strftime(%Y-%m-%d %H:%M:%S,time.localtime(time.time()))
16     print thread %s ends. % threading.current_thread().name
17 
18 if __name__ == "__main__":
19     print time.strftime(%Y-%m-%d %H:%M:%S,time.localtime(time.time()))
20     print thread %s starts. % threading.current_thread().name
21     #创建线程
22     my_thread = threading.Thread(target = test, args=(1,) , name= zni_feng_thread)
23     #等待2s
24     time.sleep(2)
25     #启动线程
26     my_thread.start()
27     #等待线程结束
28     my_thread.join()
29     print time.strftime(%Y-%m-%d %H:%M:%S,time.localtime(time.time()))
30     print thread %s ends. % threading.current_thread().name

输出结果为:

2017-01-12 22:06:32
thread MainThread starts.
2017-01-12 22:06:34
thread zni_feng_thread starts.
the index is 1
2017-01-12 22:06:37
thread zni_feng_thread ends.
2017-01-12 22:06:37
thread MainThread ends.
[Finished in 5.1s]

 其中,threading模块的current_thread()函数会返回当前线程的实例。

二、Lock

多进程与多线程的最大不同在于,多进程中,同一个变量,各自有一份拷贝存在于每个进程中,互不影响。而多线程中,所有变量都由所有线程共享,所以,任何一个共享变量都可以被任何一个线程修改。因此线程之间共享数据最大的危险在于多个线程同时改变一个变量。为了解决这个问题,我们可以借助于threading模块的Lock类给共享变量加锁。

先看看使用多线程写同一个共享变量,不加锁的例子:

 1 #!/usr/bin/python
 2 # -*- coding: utf-8 -*
 3 __author__ = zni.feng
 4 import  sys
 5 reload (sys)
 6 sys.setdefaultencoding(utf-8)
 7 import threading
 8 
 9 class Account:
10     def __init__(self):
11         self.balance = 0
12 
13     def add(self):
14         for i in range(0,100000):
15             self.balance += 1
16 
17     def delete(self):
18         for i in range(0,100000):
19             self.balance -=1 
20 
21 if __name__ == "__main__":
22     account  = Account()
23     #创建线程
24     thread_add = threading.Thread(target=account.add, name= Add)
25     thread_delete = threading.Thread(target=account.delete, name= Delete)
26 
27     #启动线程
28     thread_add.start()
29     thread_delete.start()
30     
31     #等待线程结束
32     thread_add.join()
33     thread_delete.join()
34 
35     print The final balance is:  + str(account.balance)

运行结果为:

The final balance is: -51713
[Finished in 0.1s]

可以发现,每次运行,它的最终结果都会不同,而且都不是0。就是因为不同线程在同时修改同一个变量时,发生了冲突,某些中间变量没有按顺序被使用导致。

现在我们使用Lock对程序进行加锁:

 1 #!/usr/bin/python
 2 # -*- coding: utf-8 -*
 3 __author__ = zni.feng
 4 import  sys
 5 reload (sys)
 6 sys.setdefaultencoding(utf-8)
 7 import threading
 8 
 9 class Account:
10     def __init__(self):
11         self.balance = 0
12 
13     def add(self, lock):
14         lock.acquire()
15         for i in range(0,100000):
16             self.balance += 1
17         lock.release()
18 
19     def delete(self, lock):
20         lock.acquire()
21         for i in range(0,100000):
22             self.balance -=1 
23         lock.release()
24 
25 
26 if __name__ == "__main__":
27     account  = Account()
28     lock = threading.Lock()
29     #创建线程
30     thread_add = threading.Thread(target=account.add, args=(lock, ), name= Add)
31     thread_delete = threading.Thread(target=account.delete, args=(lock, ), name= Delete)
32 
33     #启动线程
34     thread_add.start()
35     thread_delete.start()
36     
37     #等待线程结束
38     thread_add.join()
39     thread_delete.join()
40 
41     print The final balance is:  + str(account.balance)

可以发现,无论如何执行多少次,balance结果都为0。如果将每次balance计算的结果都打印出来,还会发现,当一个线程开始执行时,另一个线程一定会等到前一个线程执行完(准确地说是lock.release()执行完)后才开始执行。

The final balance is: 0
[Finished in 0.1s]

 

Python中的多进程与多线程(二)