Python多線程

什么是進程?

  • 進程是執(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()

課后延伸

了解 同步原語 ,例如 鎖 、信號量

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容