什么是進程?
- 進程是執(zhí)行中的程序
- 擁有獨立地址空間、內(nèi)存、數(shù)據(jù)棧等
- 操作系統(tǒng)管理
- 派生(fork或spawn)新進程
- 進程間通信(IPC)方式共享信息
什么是線程?
- 同進程下執(zhí)行,并共享相同的上下文
- 線程間的信息共享和通信更加容易
- 多線程并發(fā)執(zhí)行
- 需要同步原語
Python線程
- 解釋器主循環(huán)
- 主循環(huán)中只有一個控制線程在運行
- 使用全局解釋器鎖(GIL)
GIL保證一個線程
- 設(shè)置GIL
- 切換進一個線程去運行
- 執(zhí)行下面操作之一
1.指定數(shù)量的字節(jié)碼指令
2.線程主動讓出控制權(quán) - 把線程設(shè)置回睡眠狀態(tài)(切換出線程)
- 解鎖GIL
- 重復(fù)上述步驟
兩種線程管理
- _thread:提供了基本的線程和鎖
- threading:提供了更高級別、功能更全面的線程管理
1.支持同步機制
2.支持守護線程
代碼實踐
1.舉例 打印日志 (不使用線程)
import logging
from time import sleep, ctime
logging.basicConfig(level=logging.INFO)
def loop0():
logging.info("start loop0 at " + ctime())
sleep(4)
logging.info("end looo0 at " + ctime())
def loop1():
logging.info("start loop1 at " + ctime())
sleep(2)
logging.info("end looo1 at " + ctime())
def main():
logging.info("start all at " + ctime())
_thread.start_new_thread(loop0, ())
_thread.start_new_thread(loop1, ())
sleep(6) # 保護主線程運行 讓子線程執(zhí)行完
logging.info("end all at " + ctime())
if __name__ == '__main__':
main()
2.舉例 打印日志 (使用_thread 加鎖執(zhí)行)
import logging
import _thread
from time import sleep, ctime
logging.basicConfig(level=logging.INFO)
loops = [2, 4]
def loop(nloop, nsec, lock):
logging.info("start loop" + str(nloop) + " at " + ctime())
sleep(nsec)
logging.info("end loop" + str(nloop) + " at " + ctime())
lock.release()
def main():
logging.info("start all at " + ctime())
locks = []
nloops = range(len(loops))
for i in nloops:
lock = _thread.allocate_lock()
lock.acquire()
locks.append(lock)
for i in nloops:
_thread.start_new_thread(loop, (i, loops[i], locks[i]))
for i in nloops:
while locks[i].locked(): pass
logging.info("end all at " + ctime())
if __name__ == '__main__':
main()
3.舉例 打印日志 (使用threading 自帶鎖(join)執(zhí)行)
import logging
import threading
from time import sleep, ctime
logging.basicConfig(level=logging.INFO)
loops = [2, 4]
def loop(nloop, nsec):
logging.info("start loop" + str(nloop) + " at " + ctime())
sleep(nsec)
logging.info("end loop" + str(nloop) + " at " + ctime())
def main():
logging.info("start all at " + ctime())
threads = []
nloops = range(len(loops))
for i in nloops:
t = threading.Thread(target=loop, args=(i, loops[i]))
threads.append(t)
for i in nloops:
threads[i].start()
for i in nloops:
threads[i].join() //自行判斷進程是否結(jié)束 否則阻塞
logging.info("end all at " + ctime())
if __name__ == '__main__':
main()
4.舉例 打印日志 (使用類繼承 Thread threading執(zhí)行)
import logging
import threading
from time import sleep, ctime
logging.basicConfig(level=logging.INFO)
loops = [2, 4]
class MyThread(threading.Thread):
def __init__(self, func, args, name=''):
threading.Thread.__init__(self)
self.func = func
self.args = args
self.name = name
def run(self):
self.func(*self.args)
def loop(nloop, nsec):
logging.info("start loop" + str(nloop) + " at " + ctime())
sleep(nsec)
logging.info("end loop" + str(nloop) + " at " + ctime())
def main():
logging.info("start all at " + ctime())
threads = []
nloops = range(len(loops))
for i in nloops:
t = MyThread(loop, (i, loops[i]), loop.__name__)
threads.append(t)
for i in nloops:
threads[i].start()
for i in nloops:
threads[i].join() #自行判斷進程是否結(jié)束 否則阻塞
logging.info("end all at " + ctime())
if __name__ == '__main__':
main()
課后延伸
了解 同步原語 ,例如 鎖 、信號量