Python的多线程(threading)与多进程(multiprocessing)

  • 格式:pdf
  • 大小:134.35 KB
  • 文档页数:3

Python的多线程(threading)与多进程(multiprocessing)

进程:程序的⼀次执⾏(程序载⼊内存,系统分配资源运⾏)。每个进程有⾃⼰的内存空间,数据栈等,进程之间可以进⾏通讯,但是不能共享信息。

线程:所有的线程运⾏在同⼀个进程中,共享相同的运⾏环境。每个独⽴的线程有⼀个程序⼊⼝,顺序执⾏序列和程序的出⼝。

线程的运⾏可以被强占,中断或者暂时被挂起(睡眠),让其他的线程运⾏。⼀个进程中的各个线程共享同⼀⽚数据空间。

多线程

import threading

def thread_job():

print "this is added thread,number is {}".format(threading.current_thread())

def main():

added_thread = threading.Thread(target = thread_job) #添加线程

added_thread.start() #执⾏添加的线程

print threading.active_count() #当前已被激活的线程的数⽬

print threading.enumerate() #激活的是哪些线程

print threading.current_thread() #正在运⾏的是哪些线程

if __name__ == "__main__":

main()

this is added thread,number is 6

[, , , <_MainThread(MainThread, started 1528)>,

<_MainThread(MainThread, started 1528)>

#join 功能 等到线程执⾏完之后 再回到主线程中去

import threading

import time

def T1_job():

print "T1 start\n"

for i in range(10):

time.sleep(0.1)

print "T1 finish"

def T2_job():

print 'T2 start'

print 'T2 finish'

def main():

thread1 = threading.Thread(target = T1_job) #添加线程

thread2 = threading.Thread(target = T2_job)

thread1.start() #执⾏添加的线程

thread2.start()

thread1.join()

thread2.join()

print 'all done\n'

if __name__ == "__main__":

main()

T1 start

T2 start

T2 finish

T1 finish

all done

#queue 多线程各个线程的运算的值放到⼀个队列中,到主线程的时候再拿出来,以此来代替

#return的功能,因为在线程是不能返回⼀个值的

import time

import threading

from Queue import Queue

def job(l,q):

q.put([i**2 for i in l])

def multithreading(data):

q = Queue()

threads = []

for i in xrange(4):

t = threading.Thread(target = job,args = (data[i],q))

t.start()

threads.append(t)

for thread in threads:

thread.join()

results = []

for _ in range(4):

results.append(q.get())

print results

if __name__ == "__main__":

data = [[1,2,3],[4,5,6],[3,4,3],[5,5,5]]

multithreading(data)

[[1, 4, 9], [16, 25, 36], [9, 16, 9], [25, 25, 25]]

#多线程的锁

import threading

import time

def T1_job():

global A,lock

lock.acquire()

for i in xrange(10):

A += 1

print 'T1_job',A

lock.release()

def T2_job():

global A,lock

lock.acquire()

for i in xrange(10):

A += 10

print 'T2_job',A

lock.release()

if __name__ == "__main__":

lock = threading.Lock()

A = 0 #全局变量

thread1 = threading.Thread(target = T1_job) #添加线程

thread2 = threading.Thread(target = T2_job)

thread1.start() #执⾏添加的线程

thread2.start()

thread1.join()

thread2.join()

全局解释器锁GIL(Global Interpreter Lock)

GIL并不是Python的特性,他是CPython引⼊的概念,是⼀个全局排他锁。

解释执⾏python代码时,会限制线程对共享资源的访问,直到解释器遇到I/O操作或者操作次数达到⼀定数⽬时才会释放GIL。

所以,虽然CPython的线程库直接封装了系统的原⽣线程,但CPython整体作为⼀个进程,同⼀时间只会有⼀个获得GIL的线程在跑,其他线程则处于等待状态。这就造成了即使

在多核CPU中,多线程也只是做着分时切换⽽已,所以多线程⽐较适合IO密集型,不太适合CPU密集型的任务。

同⼀时刻⼀个解释进程只有⼀⾏bytecode 在执⾏

#python中 多线程的效率不⼀定就是 3 个线程就 三倍的效率

#在python中有GIL,线程锁,保证只有⼀个线程在计算,在不停的切换

#所以 如果是不同的任务,任务之间差别很⼤,线程之间可以分⼯合作,可以提⾼效率,如⼀个发送消息,另⼀个接收消息。

#如果处理⼀⼤堆的数据,多线程帮不上,需要mutliprocessing 因为每个核有单独的逻辑空间,互相不影响

import time

import threading

from Queue import Queue

def job(l,q):

q.put(sum(l))

def normal(l):

print sum(l)

def multithreading(l):

q = Queue()

threads = []

for i in range(3):

t = threading.Thread(target = job,args = (l,q),name = 'T{}'.format(i))

t.start()

threads.append(t)

[t.join() for t in threads]

total = 0

for _ in range(3):

total += q.get()

print total

if __name__ == '__main__':

l = list(xrange(1000000))

s_t = time.time()

normal(l*3)

print 'normal time:',time.time()-s_t

s_t = time.time()

multithreading(l)

print 'multithreading time:',time.time() -s_t

1499998500000

normal time: 0.297999858856

1499998500000

multithreading time: 0.25200009346

 多进程

multiprocessing库弥补了thread库因为GIL⽽低效的缺陷。完整的复制了⼀套thread所提供的接⼝⽅便迁移,唯⼀的不同就是他使⽤了多进程⽽不是多线程。每个进程都有⾃⼰独

⽴的GIL。但是在windows下多进程的开销要⽐多线程要⼤好多,Linux下是差不多的。多进程更加稳定,

multiprocessing Process类代表⼀个进程对象。

import multiprocessing as mp

import threading as td

import time

def job(q):

res = 0

for i in range(100000):

res += i + i **2

q.put(res)

def normal():

res = 0

for i in range(100000):

res += i + i **2

print 'normal:',res

def multithread():

q = mp.Queue() #这⾥⽤多进程的queue没问题的

t1 = td.Thread(target = job,args = (q,))

# t2 = td.Thread(target = job(q,))

t1.start()

# t2.start()

t1.join()

# t2.join()

res1 = q.get()

# res2 = q.get()