Python中的多进程与多线程(二)
在上一章中,学习了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]
Python中的多进程与多线程(二)的更多相关文章
- python中的多进程与多线程(二)
1.使用多线程可以有效利用CPU资源,线程享有相同的地址空间和内存,这些线程如果同时读写变量,导致互相干扰,就会产生并发问题,为了避免并发问题,绝不能让多个线程读取或写入相同的变量,因此python中 ...
- 深入浅析python中的多进程、多线程、协程
深入浅析python中的多进程.多线程.协程 我们都知道计算机是由硬件和软件组成的.硬件中的CPU是计算机的核心,它承担计算机的所有任务. 操作系统是运行在硬件之上的软件,是计算机的管理者,它负责资源 ...
- 聊聊Python中的多进程和多线程
今天,想谈一下Python中的进程和线程. 最近在学习Django的时候,涉及到了多进程和多线程的知识点,所以想着一下把Python中的这块知识进行总结,所以系统地学习了一遍,将知识梳理如下. 1. ...
- 学习笔记--python中使用多进程、多线程加速文本预处理
一.任务描述 最近尝试自行构建skip-gram模型训练word2vec词向量表.其中有一步需要统计各词汇的出现频率,截取出现频率最高的10000个词汇进行保留,形成常用词词典.对于这个问题,我建立了 ...
- Python中的多进程、多线程和协程
本文中的内容来自我的笔记.撰写过程中参考了胡俊峰老师<Python程序设计与数据科学导论>课程的内容. 并发处理:多进程和多线程 前置 概念: 并发:一段时间内同时推进多个任务,但不一定要 ...
- Python中的多进程与多线程(一)
一.背景 最近在Azkaban的测试工作中,需要在测试环境下模拟线上的调度场景进行稳定性测试.故而重操python旧业,通过python编写脚本来构造类似线上的调度场景.在脚本编写过程中,碰到这样一个 ...
- Python中的多进程与多线程/分布式该如何使用
在批评Python的讨论中,常常说起Python多线程是多么的难用.还有人对 global interpreter lock(也被亲切的称为“GIL”)指指点点,说它阻碍了Python的多线程程序同时 ...
- python中的多进程与多线程(一)
进程是一个执行中的程序,每个进程有自己的地址空间.内存.数据栈以及其他用于跟踪执行的辅助数据.操作系统管理其上所有进程,并合理分配时间. 进程也可以通过fork或spawn派生新的进程,每个新进程有自 ...
- Python中使用多进程来实现并行处理的方法小结
进程和线程是计算机软件领域里很重要的概念,进程和线程有区别,也有着密切的联系,先来辨析一下这两个概念: 1.定义 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和 ...
随机推荐
- Visual Studio Contact
Visual Studio Contact(); 直播笔记 昨天微软干了几件了不起的事:.NET开发环境将开源.跨平台支持(Mac OS X和Linux).多设备支持(WP.Android和iOS ...
- leetcode第12题--Integer to Roman
Problem: Given an integer, convert it to a roman numeral. Input is guaranteed to be within the range ...
- CodeIgniter框架文件结构
转自网络:http://my.oschina.net/scholer/blog/99226 这个本来是很基础的东西,基本上用过CI的人都知道这些,原本是不消说的~但是因为毕业论文是关于CodeIgni ...
- 实例学习SSIS(三)--使用包配置
原文:实例学习SSIS(三)--使用包配置 导读: 实例学习SSIS(一)--制作一个简单的ETL包 实例学习SSIS(二)--使用迭代 实例学习SSIS(三)--使用包配置 实例学习SSIS(四)- ...
- Javascript多线程引擎(六)
Javascript多线程引擎(六) 经过三个月的时间, Javascript 引擎已经完成beta版本(还不支持多线程特性, 预计下个星期就可以支持了, 现阶段还在进行测试基本JS单元功能), 并且 ...
- Linux--Windows与Linux互传文件
用惯了windows下的复制粘贴,转到Linux下确实不习惯,而且对于windows上搭建的windows的虚拟机,从主机到虚拟机之间无缝的复制粘贴,想从windows下拷贝文件到命令行的linux下 ...
- 【分享】Python学习资源大合集
地址:http://www.hejizhan.com/html/xueke/520/x520_03.html Python安装软件合集(Windows)(78) Python教程——游戏编程(13) ...
- ModelBinder——ASP.NET MVC Model绑定的核心
ModelBinder——ASP.NET MVC Model绑定的核心 Model的绑定体现在从当前请求提取相应的数据绑定到目标Action方法的参数.通过前面的介绍我们知道Action方法的参数通过 ...
- Love myself...
Sometimes we feel as if our lives rely on that one person. We think 'If I do this, he/she will like ...
- 玩转python之测试一个对象是否是类字符串
提到类型测试,我首先想到python中“鸭子类型”的特点,所谓鸭子类型,即如果它走路像鸭子,叫声也像鸭子, 那么对于我们的应用而言,就可以认为它是鸭子了!这一切都是为了功能复用. 我们总是需要测试一个 ...