python进程和线程

单进程

from multiprocessing import Process
import os

def run_proc(name):
	print 'the %s process id is %d.' %(name,os.getpid())
	
if __name__=='__main__':
	print 'the parent process id is %d.' %os.getpid()
	p=Process(target=run_proc,args=('test',))
	print 'process will begin.'
	p.start()
	p.join()
	print 'process end.'

pool

# -*- coding:utf-8 -*-

from multiprocessing import Pool
import os,time,random


#值得注意的是,各子进程是同时运行的,这一点至关重要
def f(x):  #子进程的执行程序
	print 'task %d id is %d' %(x,os.getpid())
	start=time.time()
	time.sleep(random.random()*5)
	end=time.time()
	print 'task %d ran %0.2f seconds.' %(x,(end-start))
	#每个子进程运行的时间是0~5秒的随机时间
	
if __name__=='__main__':
	print 'parent id is %d' %(os.getpid())
	
	p=Pool(processes=3) #池容量为3个进程,即同时(最多)可以运行3个进程
	for i in range(5):  #创建5个进程,但并未开始运行(挂起)
		p.apply_async(f,(i,))
	print 'processes will begin'
	p.close() #各子进程结束后,关闭pool
	p.join()  #等待子进程结束后,主进程再结束
	print 'the end'
	
'''
创建5个进程:我们有5名参赛运动员
池容量是3:我们有3条泳道,每条泳道上每次至多只能有一名运动员
p.apply_async,5名运动员赛前准备,未开始比赛
p.close(),一声哨响,前3名运动员率先比赛,同时执行f(x)——子进程开始运行
每名运动员开始游泳前,喊一声:我是多少号,我要开始游了!
          到终点了,喊一声,我到终点了!!
第4名运动员上,虽然它游的晚,但是仍然有可能超越先游的,先到达终点
等到又有一名运动员到终点了,第5名运动员上,......
'''

进程通信,工具Queue,Pipe

# -*- coding:utf-8 -*-

from multiprocessing import Queue,Process
import os,time,random

def write(q):
	for i in ['a','b','c']:
		print 'put %s to queue.' %i
		q.put(i)
		time.sleep(random.random()) 
#有了这一句才能写一个读一个,要不然还来不及读就写完了
		
def read(q):
	while True:
		i=q.get(True)
		print 'get %s from queue.' %i

if __name__=='__main__':
	q=Queue() #两个进程都用到q,所以q是沟通进程的桥梁,先进先出!
	pw=Process(target=write,args=(q,)) #创建进程实例
	pr=Process(target=read,args=(q,))
	print 'time is ready'
	pw.start()
	pr.start()
	pw.join()
	pr.terminate()#pr是死循环,必须手动终止进程
	print 'the end'
	

创建一个线程

# -*- coding:utf-8 -*-

#pyhton多线程编程:threading高级模块
#启动一个线程就是把一个函数传入并创建Thread实例,然后调用start()开始执行

import time,threading

def loop():   #线程的执行程序
	print 'thread %s is running...' %threading.current_thread().name
	time.sleep(3)
	print 'thread %s is ended.' %threading.current_thread().name

print 'thread %s is running...' %threading.current_thread().name
t=threading.Thread(target=loop) 
#创建Thread()进程实例并挂起,其实只创建了一个线程而已
#如果想给主线程创建的线程指定线程名称,可以用 t=threading.Thread(target=loop,name='subthread') 
t.start() #线程开始执行,即运行loop程序
t.join() #等待线程运行结束
print 'thread %s is ended.' %threading.current_thread().name

创建两个线程,看各线程间是如何共享变量的

# -*- coding:utf-8 -*-

import time,threading

balance=0
	
def runthread(n):
	for i in range(10000):
		global balance
		balance=balance+n
		balance=balance-n

if __name__=='__main__':
	th1=threading.Thread(target=runthread,args=(5,))
	th2=threading.Thread(target=runthread,args=(8,))
	th1.start()
	th2.start()
	th1.join()
	th2.join()
	print balance

结果打印的balance的值是无法预料的,很大可能性不为0(具体的要用到汇编语言来解释,csapp上有述)

避免上面的情况,就要用到锁lock

# -*- coding:utf-8 -*-

import time,threading

balance=0
lock=threading.Lock()
	
def runthread(n):
	for i in range(10000):
		#先获取锁
		lock.acquire()
		try:
			global balance
			balance=balance+n
			balance=balance-n
		finally:
			#改完后要释放锁
			lock.release()

if __name__=='__main__':
	th1=threading.Thread(target=runthread,args=(5,))
	th2=threading.Thread(target=runthread,args=(8,))
	th1.start()
	th2.start()
	th1.join()
	th2.join()
	print balance
锁的好处就是确保了某段关键代码只能由一个线程从头到尾完整地执行(如try段的代码就会一次性执行完),坏处当然也很多,首先是阻止了多线程并发执行, 包含锁的某段代码实际上只能以单线程模式执行,效率就大大地下降了。由于可以存在多个锁,不同的线程持有不同的锁,并试图获取对方持有的锁时,可能会造成死锁,导致多个线程全部挂起,既不能执行,也无法结束,只能靠操作系统强制终止。

解释一下python的GIL锁

任何Python线程执行前,必须先获得GIL锁(解释器全局锁),然后,每执行100条字节码,解释器就自动释放GIL锁,让别的线程有机会执行。

这个GIL全局锁实际上把所有线程的执行代码都给上了锁,所以,多线程在Python中只能交替执行,也就是说,对于任何Python程序,不管有多少的处理器,任何时候都总是只有一个线程在执行,即使100个线程跑在100核CPU上,也只能用到1个核(每次只有一个线程在执行,当然只用一个 核 喽!)。

ThreadLocal

# -*- coding:utf-8 -*-

'''
ThreadLocal
'''

import threading,time
local_school=threading.local()

def run_process():
	print '%s in %s' %(local_school.student,threading.current_thread().name)
	time.sleep(2)
	print '%s is over' %threading.current_thread().name
	
def runthread(mylove):
	local_school.student=mylove
	#实质相当于local_school.student[threading.current_thread().name]=mylove
	#根据线程的名字来标识变量,这样就不会访问错了
	run_process()
	#在线程中调用程序,那么那个程序自然可以知道调用自己的线程的名字!!!
	
if __name__=='__main__':
	th1=threading.Thread(target=runthread,name='thread1',args=('zhuma',))
	th2=threading.Thread(target=runthread,name='thread2',args=('zhangpan',))
	th1.start()
	th2.start()
	th2.join()
	th1.join()
	


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值