串行:同一个时间段只干一件事
并行:同一个时间段可以干多件事
并发 V.S. 并行
并发是指一个时间段内,有几个程序在同一个CPU上运行,但是任意时刻只有一个程序在CPU上运行。
并行是指任意时刻点上,有多个程序同时运行在多个CPU上,即每个CPU独立运行一个程序。
并行的最大数量和CPU的数量是一致的。
同步 V.S. 异步:
同步是指代码调用IO操作时,必须等待IO操作完成返回才调用的方式
异步是指代码调用IO操作时,不必等待IO操作完成返回才调用的方式
多线程:交替执行,另一种意义上的串行
比进程的概念小,减少了进程切换过程中的消耗
多进程:并行执行,真正意义上的并行
通过切换不同的进程来实现多任务的并行
多进程 V.S. 多线程:
由于全局解释锁GIL的存在,Python的多线程无法利用多核优势,所以不适合计算密集型任务,适合IO密集型任务。
CPU密集型任务适合使用多进程
进程切换代价要高于线程
线程之间可以通过全局变量来进行通信,但是进程不行。进程之间的数据是完全隔离的。
threading类:
threading.Lock():同步锁(互斥锁),解决数据安全问题
threading.RLock():递归锁,解决线程死锁问题
threading.Semaphore():信号量,最多允许同时有n个线程,超过信号量的线程会被堵塞,直到有线程的信号量被释放。
threading.Event():事件,让不同的线程保持同步而不是独立的运行,彼此交互:你给我发一个信号,我接到了执行一个操作,再给你发一个信号,你接到了执行操作并继续发信号……
锁
import threading
#生成锁对象,全局唯一
lock = threading.Lock()
#获取锁
lock.acquire()
#释放锁
lock.release()
可以使用上下文管理协议来管理锁
lock = threading.Lock()
with lock:
pass
#等价于:
lock.acquire()
try:
pass
finally:
lock.release()
加锁会影响性能,获取锁和释放锁都需要时间。
使用锁可能会引起死锁
多线程
import threading
import time
def sleeper(n,name):
print('Hi, I`m {}. I`m going to sleep 5 seconds'.format(name))
time.sleep(n)
print('{} has woken up from sleep'.format(name))
e.g.1
def main():
t = threading.Thread(target = sleeper, args = (5,'thread1'))
t.start()
#调用.join()方法来阻塞当前线程,直到该线程结束后,才跳转执行其余的线程
#t.join() 如果加上这个语句,程序需要等整个sleeper执行完毕后才会跳回执行后面的两次print
print('hello')
print('hello')
>>
Hi, I`m thread1. I`m going to sleep 5 seconds.
hello
hello
thread1 has woken up from sleep.
e.g.2
def main():
start = time.time()
thread_list = []
for i in range(1,6):
t = threading.thread(target=sleeper, args=(5,'thread{}'.format(i)))
thread_list.append(t)
t.start()
print('{} has started.'.format(t.name)
for t in thread_list:
t.join()
end = time.time()
print('total time: {}'.format(end - start))
print('aaa')
>>
Hi, I`m thread1. I`m going to sleep 5 seconds
Thread-1 has started.
Hi, I`m thread2. I`m going to sleep 5 seconds
Thread-2 has started.
Hi, I`m thread3. I`m going to sleep 5 seconds
Thread-3 has started.
Hi, I`m thread4. I`m going to sleep 5 seconds
Thread-4 has started.
thread2 has woken up from sleep
thread1 has woken up from sleep
thread4 has woken up from sleep
thread3 has woken up from sleep
total time: 5.001285791397095
aaa
e.g.3
def main():
start = time.time()
thread_list = []
for i in range(1,6):
t = threading.thread(target=sleeper, args=(5,'thread{}'.format(i)))
thread_list.append(t)
t.start()
t.join() #阻塞进程
print('{} has started.'.format(t.name)
end = time.time()
print('total time: {}'.format(end - start))
print('aaa')
>>
Hi, I`m thread1. I`m going to sleep 5 seconds
thread1 has woken up from sleep
Thread-1 has started.
Hi, I`m thread2. I`m going to sleep 5 seconds
thread2 has woken up from sleep
Thread-2 has started.
Hi, I`m thread3. I`m going to sleep 5 seconds
thread3 has woken up from sleep
Thread-3 has started.
Hi, I`m thread4. I`m going to sleep 5 seconds
thread4 has woken up from sleep
Thread-4 has started.
total time: 20.00114393234253
aaa
线程之间通信的方法
queue:
queue是线程安全的,其源码中已经使用了锁
queue也是共享变量的一种,只是它自身已经具有线程安全性。如果换成其他变量可能会出现不同步的问题。
常用方法:
from queue import Queue
put(self, item, block=True, timeout=None):将元素加入队列&#x