并发编程
一、概念
1、非并发
程序由单个步骤序列构成
包含独立子任务的程序执行性能低
2、并发
1)异步
2)分解子任务、简化流程与逻辑
3、进程 process
一个程序的执行实例
每个进程有自己的地址空间、内存、数据栈及辅助数据
4、线程 thread
同一个进程内,可被并行激活的控制流
共享相同上下文(空间地址、数据结构)
特点:1) 便于信息共享与通信
2) 线程访问顺序差异会导致结果不一致(条件,race,condition)
5、Python GIL 全局解释器锁
Global Interpreter Lock
Python代码由虚拟机(解释器主循环)控制完成
主循环同时只能有一个控制线程执行
I/O密集型程序,建议使用多线程
计算密集型程序,建议使用多进程
二、多线程之threading模块
1、.Tread 线程类
通过基类去执行
import time
import threading
def worker(sleep_time):
print('{} worker 函数开始于:{}'.format(threading.current_thread().name,time.ctime()))
time.sleep(sleep_time)
print('{} worker 函数结束于:{}'.format(threading.current_thread().name, time.ctime()))
if __name__ == '__main__':
print('主函数开始于:{}'.format(time.ctime()))
threads = []
t1 = threading.Thread(target=worker, args=(4,))
threads.append(t1)
t2 = threading.Thread(target=worker, args=(2,))
threads.append(t2)
for t in threads:
t.start()
for t in threads:
t.join()
print('主函数结束于:{}'.format(time.ctime()))
通过派生类去执行
import time
import threading
def worker(sleep_time):
print('{} worker 函数开始于:{}'.format(threading.current_thread().name,time.ctime()))
time.sleep(sleep_time)
print('{} worker 函数结束于:{}'.format(threading.current_thread().name, time.ctime()))
class MyThread(threading.Thread):
def __init__(self, func, args):
threading.Thread.__init__(self)
self.func = func
self.args = args
def run(self):
self.func(*self.args)
if __name__ == '__main__':
print('主函数开始于:{}'.format(time.ctime()))
threads = []
t1 = MyThread(worker, (4,))
threads.append(t1)
t2 = MyThread(worker, (2,))
threads.append(t2)
for t in threads:
t.start()
for t in threads:
t.join()
print('主函数结束于:{}'.format(time.ctime()))
三、同步锁
.acquire() 获得锁
.release() 释放锁
with lock: 支持上下文操作
import time
import threading
import random
eggs = []
lock = threading.Lock()
def put_eggs(num, lst):
# lock.acquire()
# for i in range(1, num+1):
# time.sleep(random.randint(0,2))
# lst.append(i)
# lock.release()
with lock:
for i in range(1, num+1):
time.sleep(random.randint(0,2))
lst.append(i)
def main():
threads = []
for i in range(0, 3):
t = threading.Thread(target=put_eggs, args=(5,eggs))
threads.append(t)
for t in threads:
t.start()
for t in threads:
t.join()
if __name__ == '__main__':
main()
print(eggs)
四、队列
queue模块
import time
import threading
import random
import queue
q = queue.Queue()
def producer(data_queue):
for i in range(5):
time.sleep(0.5)
m = random.randint(1,100)
data_queue.put(m)
print(f'{threading.current_thread().name}往队列中添加了一个元素{m}')
def consumer(data_queue):
while True:
try:
m = data_queue.get(timeout=2)
time.sleep(random.randint(0,2))
print(f'{threading.current_thread().name}从队列中移除了一个元素{m}')
except queue.Empty:
break
else:
data_queue.task_done()
def main():
threads = []
p = threading.Thread(target=producer,args=(q,))
p.start()
time.sleep(3)
for i in range(0,2):
t = threading.Thread(target=consumer, args=(q,))
threads.append(t)
for t in threads:
t.start()
for t in threads:
t.join()
if __name__ == '__main__':
main()
Thread-1往队列中添加了一个元素47
Thread-1往队列中添加了一个元素75
Thread-1往队列中添加了一个元素79
Thread-1往队列中添加了一个元素5
Thread-1往队列中添加了一个元素16
Thread-2从队列中移除了一个元素47
Thread-2从队列中移除了一个元素79
Thread-2从队列中移除了一个元素5
Thread-3从队列中移除了一个元素75
Thread-2从队列中移除了一个元素16
五、多进程之multiprocessing模块
用法和threading模块一样,但是多进程可以充分利用多核多CPU的计算能力,适合计算密集型程序
六、concurrent.futures 模块
import time
import threading
import random
import queue
import concurrent.futures
num_pool = list(range(1,11))
def count(n):
for i in range(10000000):
i += i
return i * n
def worker(x):
res = count(x)
print(f'数字{x}的计算结果是{res}')
def seq_execution():
start_time = time.clock()
for i in num_pool:
worker(i)
print(f'顺序执行的耗时是:{time.clock()-start_time}秒')
def thread_execution():
start_time = time.clock()
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
for i in num_pool:
executor.submit(worker, i)
print(f'多线程执行的耗时是:{time.clock()-start_time}秒')
def process_execution():
start_time = time.clock()
with concurrent.futures.ProcessPoolExecutor(max_workers=5) as executor:
for i in num_pool:
executor.submit(worker, i)
print(f'多进程执行的耗时是:{time.clock()-start_time}秒')
if __name__ == '__main__':
# seq_execution()
# thread_execution()
process_execution()