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

一、threading

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

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

 #!/usr/bin/python
# -*- coding: utf-8 -*
__author__ = 'zni.feng'
import sys
reload (sys)
sys.setdefaultencoding('utf-8') import threading, time def test(index):
print time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
print 'thread %s starts.' % threading.current_thread().name
print 'the index is %d' % index
time.sleep(3)
print time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
print 'thread %s ends.' % threading.current_thread().name if __name__ == "__main__":
print time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
print 'thread %s starts.' % threading.current_thread().name
#创建线程
my_thread = threading.Thread(target = test, args=(1,) , name= 'zni_feng_thread')
#等待2s
time.sleep(2)
#启动线程
my_thread.start()
#等待线程结束
my_thread.join()
print time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
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类给共享变量加锁。

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

 #!/usr/bin/python
# -*- coding: utf-8 -*
__author__ = 'zni.feng'
import sys
reload (sys)
sys.setdefaultencoding('utf-8')
import threading class Account:
def __init__(self):
self.balance = 0 def add(self):
for i in range(0,100000):
self.balance += 1 def delete(self):
for i in range(0,100000):
self.balance -=1 if __name__ == "__main__":
account = Account()
#创建线程
thread_add = threading.Thread(target=account.add, name= 'Add')
thread_delete = threading.Thread(target=account.delete, name= 'Delete') #启动线程
thread_add.start()
thread_delete.start() #等待线程结束
thread_add.join()
thread_delete.join() print 'The final balance is: ' + str(account.balance)

运行结果为:

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

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

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

 #!/usr/bin/python
# -*- coding: utf-8 -*
__author__ = 'zni.feng'
import sys
reload (sys)
sys.setdefaultencoding('utf-8')
import threading class Account:
def __init__(self):
self.balance = 0 def add(self, lock):
#获得锁
lock.acquire()
for i in range(0,100000):
self.balance += 1
#释放锁
lock.release() def delete(self, lock):
#获得锁
lock.acquire()
for i in range(0,100000):
self.balance -=1
#释放锁
lock.release() if __name__ == "__main__":
account = Account()
lock = threading.Lock()
#创建线程
thread_add = threading.Thread(target=account.add, args=(lock, ), name= 'Add')
thread_delete = threading.Thread(target=account.delete, args=(lock, ), name= 'Delete') #启动线程
thread_add.start()
thread_delete.start() #等待线程结束
thread_add.join()
thread_delete.join() print 'The final balance is: ' + str(account.balance)

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

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

最新文章

  1. C#基础——静态成员,static关键字
  2. 【228】◀▶ Excel 函数说明
  3. Spring Batch学习
  4. MongoDB (三) MongoDB 安装
  5. linux系统环境变量.bash_profile/bashrc文件
  6. 非常有用的Java程序片段
  7. 关于win7右下角显示“音频服务未运行”的解决方法
  8. SQL随笔
  9. mui实现退出当前应用
  10. C 和 C++的 不同
  11. 《码农周刊》干货精选(Python 篇)
  12. JSP页面小脚本实现日期比較,Java同理,精简过后的,可能在效率上不太好,有大大能够给优化下就更好了
  13. JAVA对特殊的字符串进行html编码
  14. jquery 实现tab切换
  15. php 随机红包算法
  16. 2082 : Only choose one
  17. 日常推荐大神操作,如何再oracle中delete数据后恢复
  18. Java中A instanceof B是什么意思?
  19. android 按钮特效 波纹 Android button effects ripple
  20. myeclise中创建maven web程序

热门文章

  1. AngularJS学习笔记(一)——一些基本知识
  2. C语言运算符表(优先级)
  3. C#可扩展编程之MEF
  4. ASP.NET页面生命周期和asp.net应用程序生命周期
  5. 安卓推送——个推服务端api使用误区
  6. 真与假与c#,java中的不同之处
  7. ASP.NET网站单独
  8. 清除在Windows下访问共享文件夹时的登录信息
  9. Objective-C Blocks测试题与解析
  10. IOS7学习之路九(ios7自定义UIAlertView)