概述
除了一般程式設計語言都具備的線程、程序,python還有一種‘輕量級’的線程——協程。
程序
不必贅述,和其他語言類似。
線程
python的線程是一個奇葩的存在,不同于其他語言。随着硬體技術的高速發展,各CPU廠商在核心頻率上的比賽已經被多核所取代。為了更好的利用多核優勢,随之衍生出了多線程程式設計,python自然也不能免俗。但是多線程帶來的問題是線程間資料一緻性和狀态同步,最簡單的就是加一把鎖,于是産生了一把名叫GIL的超級鎖。這把鎖的存在,使得python的多線程事實上依然隻是單線程,因為GIL限制了同一時刻,隻能有一個線程拿到鎖。正因為GIL的存在,導緻了python的多線程不是并行,隻能算并發,性能極低。
協程
協程是一種輕量級的線程。與線程的差別是,線程是由作業系統排程切換,而協程有python程式自己控制排程。

例程
多程序
關鍵詞:程序池、程序間通信、信号捕捉
#!/usr/bin/python3
import os
import signal
import time
from multiprocessing import Pool, Queue
# 建立一個queue用于程序間通信
chan = Queue()
def producer():
while 1:
now = time.time()
print('producer time: {}'.format(now))
# 入隊
chan.put_nowait(now)
time.sleep(1)
def consumer():
while 1:
if not chan.empty():
# 出隊
now = chan.get_nowait()
print('consumer time: {}'.format(now))
def sig_handler(signum, frame):
pid = os.getpid()
ppid = os.getppid()
print('[{}][{}]signal {} received, program exit...'.format(pid, ppid, signum))
exit(0)
if __name__ == '__main__':
signal.signal(signal.SIGINT, sig_handler)
signal.signal(signal.SIGHUP, sig_handler)
signal.signal(signal.SIGTERM, sig_handler)
# 建立可容納兩個子程序得程序池
pools = Pool(processes=2)
try:
pools.apply_async(producer, args=())
pools.apply_async(consumer, args=())
except Exception as e:
print('exception {} capture, program exit...'.format(e))
exit(1)
while 1:
pass
多線程
關鍵詞:多線程、線程間通信、信号捕捉
#!/usr/bin/python3
import os
import signal
import time
import _thread
import queue
# 建立一個queue用于線程間通信
chan = queue.Queue()
def producer():
while 1:
now = time.time()
print('producer time: {}'.format(now))
# 入隊
chan.put_nowait(now)
time.sleep(1)
def consumer():
while 1:
if not chan.empty():
# 出隊
now = chan.get_nowait()
print('consumer time: {}'.format(now))
def sig_handler(signum, frame):
pid = os.getpid()
ppid = os.getppid()
print('[{}][{}]signal {} received, program exit...'.format(pid, ppid, signum))
exit(0)
if __name__ == '__main__':
signal.signal(signal.SIGINT, sig_handler)
signal.signal(signal.SIGHUP, sig_handler)
signal.signal(signal.SIGTERM, sig_handler)
try:
_thread.start_new_thread(producer, ())
_thread.start_new_thread(consumer, ())
except:
print('Error: unable to start thread')
while 1:
pass
多協程
關鍵詞:協程、協程間通信、協程排程
在編寫協程時需要注意,協程需要程式自己控制切換,也就是代碼中調用
await asyncio.sleep(1)
,本質是讓producer協程陷入睡眠,交出CPU使用權,然後consumer獲得執行時機,輪換交複。
#!/usr/bin/python3
import os
import signal
import time
import asyncio
# 建立一個queue用于協程間通信
chan = asyncio.Queue()
async def producer():
while 1:
now = time.time()
# 入隊
await chan.put(now)
print('producer time: {}'.format(now))
await asyncio.sleep(1)
async def consumer():
while 1:
# 出隊
now = await chan.get()
print('consumer time: {}'.format(now))
await asyncio.sleep(1)
def sig_handler(signum, frame):
pid = os.getpid()
ppid = os.getppid()
print('[{}][{}]signal {} received, program exit...'.format(pid, ppid, signum))
exit(0)
if __name__ == '__main__':
signal.signal(signal.SIGINT, sig_handler)
signal.signal(signal.SIGHUP, sig_handler)
signal.signal(signal.SIGTERM, sig_handler)
tasks = [asyncio.ensure_future(producer()),
asyncio.ensure_future(consumer())]
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(asyncio.wait(tasks))
except Exception as e:
for task in tasks:
task.cancel()
loop.stop()
loop.run_forever()
finally:
loop.close()