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]
时间: 2024-12-25 04:43:45

Python中的多进程与多线程(二)的相关文章

Python中的多进程与多线程/分布式该如何使用

在批评Python的讨论中,常常说起Python多线程是多么的难用.还有人对 global interpreter lock(也被亲切的称为“GIL”)指指点点,说它阻碍了Python的多线程程序同时运行.因此,如果你是从其他语言(比如C++或Java)转过来的话,Python线程模块并不会像你想象的那样去运行.必须要说明的是,我们还是可以用Python写出能并发或并行的代码,并且能带来性能的显著提升,只要你能顾及到一些事情.如果你还没看过的话,我建议你看看Eqbal Quran的文章<Ruby

python并发之多进程、多线程、协程和异步

一.多线程 二.协程(又称微线程,纤程) 协程,与线程的抢占式调度不同,它是协作式调度.协程在python中可以由generator来实现. 首先要对生成器和yield有一个扎实的理解. 调用一个普通的python函数,一般是从函数的第一行代码开始执行,结束于return语句.异常或者函数执行(也可以认为是隐式地返回了None). 一旦函数将控制权交还给调用者,就意味着全部结束.而有时可以创建能产生一个序列的函数,来“保存自己的工作”,这就是生成器(使用了yield关键字的函数). 能够“产生一

Python中的多进程

由于cPython的gill,多线程未必是CPU密集型程序的好的选择. 多线程可以完全独立的进程环境中运行程序,可以充分利用多处理器. 但是进程本身的隔离带来的数据不共享也是一种问题,线程比进程轻量级. 1.Multiprocessing import multiprocessing import datetime def calc(i):     sum = 0     for _ in range(10000000):         sum += 1     print(i,sum) if

进程和线程,线程安全,python如何实现多进程,多线程

进程和线程的区别 进程是对运行时程序的封装,是系统资源调度和分配的基本单位 线程是进程的子任务,cpu调度和分配的基本单位,实现进程内并发. 一个进程可以包含多个线程,线程依赖进程存在,并共享进程内存 什么是线程安全 一个线程的修改被另一个线程的修改覆盖掉. python中哪些操作是线程安全的 一个操作可以在多线程环境中使用,并且获得正确的结果. 线程安全的操作线程是顺序执行的而不是并发执行的. 一般涉及到写操作需要考虑如何让多个线程安全访问数据. 线程同步的方式 互斥量(锁): 通过互斥机制防

[转载]python中的sys模块(二)

#!/usr/bin/python # Filename: using_sys.py import sys print 'The command line arguments are:' for i in sys.argv: print i print '\n\nThe PYTHONPATH is', sys.path, '\n' 输出结果如下 它如何工作 首先,我们利用 import 语句 输入 sys 模块.基本上,这句语句告诉 Python,我们想要使用这个模块.sys 模块包含了与 Py

python中的多进程处理

转载于:http://blog.csdn.net/jj_liuxin/article/details/3564365 帮助文档见https://docs.python.org/2.7/library/multiprocessing.html 众所周知,python本身是单线程的,python中的线程处理是由python解释器分配时间片的:但在python 3.0中吸收了开源模块,开始支持系统原生的进程处理——multiprocessing. 注意:这个模块的某些函数需要操作系统的支持,例如,mu

122 Python程序中的多进程和多线程

目录 一.什么是进程池或线程池 二.理解同步.异步. 三.multiprocess.Pool模块实现进程池 3.1.1 Pool使用方法 3.1.1 代码实例--multiprocess.Pool 四.Python标准模块--concurrent.futures实现进程池和线程池 4.1 介绍 4.2 基本方法 4.3 代码实例--ProcessPoolExecutor 方式1: 方式2: 方式3 4.4 代码实例--ThreadPoolExecutor 方式1: 方式2: 方式3: 一.什么是

服务器开发中的多进程,多线程及多协程

服务器开发中,为了充分利用多核甚至多个cpu,或者是简化逻辑编写的难度,会应用多进程(比如一个进程负责一种逻辑)多线程(将不同的用户分配到不同的进程)或者协程(不同的用户分配不同的协程,在需要时切换到其他协程),并且往往同时利用这些技术比如多进程多线程. 一个经典的服务器框架可以说如下的框架: 而这些服务器进程之间协同配合,为用户提供服务,其中中心服务器提供集群的调度工作,而逻辑服可以是逻辑服务器1提供登录服务.逻辑服务器2提供购买服务:也可以是2个服务器提供相同服务,然后视负载用户数将不同用户

python中常用模块详解二

log模块的讲解 1 Python 使用logging模块记录日志涉及四个主要类,使用官方文档中的概括最为合适: 2 3 logger提供了应用程序可以直接使用的接口API: 4 handler将(logger创建的)日志记录发送到合适的目的输出: 5 formatter决定日志记录的最终输出格式 6 filter提供了细度设备来决定输出哪条日志记录: 7 8 logger 9 每个程序在输出信息之前都要获得一个Logger.Logger通常对应了程序的模块名, 10 比如聊天工具的图形界面模块