Python 多进程和多线程
多进程
fork
学过linux 系统API的人都知道,使用C编写多进程程序时,使用系统调用fork,fork函数调用一次返回两次,在父进程返回一次,值为子进程进程ID,在子进程返回一次,值为0.同样在Python中的特征也和C中相同。使用这种方式这能在POSIX标准的系统中使用。
多进程的特点:
1.子进程和父进程分属两个进程空间,子进程修改变量的值,父进程不会受到影响。
2.子进程会继承父进程文件描述符,在linux系统中一切皆文件,文件描述符可能是文件socket或者其他。
import os
import time
pid = os.fork()
f = open('aaa.txt','r+')
if pid == 0 :
time.sleep(5)
a = f.read()
print("child %s" % a)
else:
print("child%s" % pid)
f.write('asfd')
'''
结果:
child31313 #父进程打出子进程pid然后退出程序
child asfd #子进程打印读出的数据并退出
'''
multiprocessing 跨平台多进程
Process 单个子进程
from multiprocessing import Process
def proc(a, b): #定义子进程执行过程
print("child",a,b)
print("main")
p = Process(target=proc , args=('aaa','bbb')) #实例化子进程对象,设置执行过程和参数
p.start()#开启子进程
p.join()#主进程等待子进程结束
print("main end")
'''
结果:
main
child aaa bbb
main end
'''
Pool 进程池
from multiprocessing import Pool
import os
import time
def proc(a):
time.sleep(2)
print(a,os.getpid()) #getpid获取进程id
p = Pool(4)#设置进程池大小为4
for x in range(5): #新建5个进程
p.apply_async(proc,args=(x,))
p.close() #close就不可以在进程池中加入新进程
p.join() #等待子进程全部结束
'''
结果:
3 2205
2 2206
1 2207
0 2208
4 2205
'''
进程间通信
学过linux系统编程的人都应该很熟悉,例如下:
1. Queue
from multiprocessing import Process, Queue
import time
def readProc(que):
while True:
a = que.get() #从队列中获取,没有则等待
print("read %s" % a )
def writeProc(que):
x = 0;
while True:
time.sleep(1)
que.put(x)#把x写入队列
print('write %s' % x )
x+=1
q = Queue()
a = Process(target=writeProc , args=(q,));
b = Process(target=readProc, args=(q,))
a.start()
b.start()
a.join()
'''
结果:
write 0
read 0
write 1
read 1
write 2
read 2
write 3
read 3
...
'''
- Pipe
from multiprocessing import Process, Pipe
def proc(p):
a = p.recv()#接收send发送的内容
print("child",a)
parent,child = Pipe()#获取管道的两端
p = Process(target=proc, args=(child,))
p.start()
parent.send('aaa')#发送数据
p.join()
'''
结果:child aaa
'''
多线程
线程创建
from threading import Thread
def threadProc():#线程处理过程
print("thread")
t = Thread(target=threadProc) #创建线程
print("main")
t.start()#开启线程
t.join()
'''
结果:
main
thread
'''
线程同步互斥
和进程不一样,进程间不能互相访问对方的进程空间,多线程是在同一个进程下,可以访问进程资源,对于共享资源同一时间读写操作不能同时进行,否则数据的内容可能不是我们想要的结果。
from threading import Thread,Lock
import time
lock = Lock() #实例化锁对象
def threadProc():
lock.acquire() #获取锁 同一个锁对象只能有一个持有锁和 pthread_mutex_lock一样,获取不到则阻塞
time.sleep(2)
print("thread")
lock.release()#释放锁 同pthread_mutex_unlock一样,释放后别的线程才能获取
def threadProc2():
lock.acquire()
time.sleep(2)
print("thread2")
lock.release()
t = Thread(target=threadProc)
t1 = Thread(target=threadProc2)
print("main")
t.start()
t1.start()
t.join()
t1.join()
'''
结果:
main
thread
thread2
'''
ThreadLocal
from threading import Thread,local
import time
threadLocal = local() #创建local对象
def show(name):
print(name,threadLocal.a)
def thread1():
threadLocal.a = 'thread1';
show('thread1')
time.sleep(1)
def thread2():
threadLocal.a = 'thread2';
show('thread2')
time.sleep(1)
threadp1 = Thread(target = thread1)
threadp2 = Thread(target = thread2)
threadp1.start()
threadp2.start()
threadp1.join()
threadp2.join()
'''
结果:
thread1 thread1
thread2 thread2
'''
上述例子可以看出,在threadLocal中每个线程都是独立的,不会被其他线程访问到,看似是全局变量,但是表现的特性是每个线程有自己独立的空间。