Python多线程

什么是进程?

  • 进程是执行中的程序
  • 拥有独立地址空间、内存、数据栈等
  • 操作系统管理
  • 派生(fork或spawn)新进程
  • 进程间通信(IPC)方式共享信息

什么是线程?

  • 同进程下执行,并共享相同的上下文
  • 线程间的信息共享和通信更加容易
  • 多线程并发执行
  • 需要同步原语

Python线程

  • 解释器主循环
  • 主循环中只有一个控制线程在运行
  • 使用全局解释器锁(GIL)

GIL保证一个线程

  • 设置GIL
  • 切换进一个线程去运行
  • 执行下面操作之一
    1.指定数量的字节码指令
    2.线程主动让出控制权
  • 把线程设置回睡眠状态(切换出线程)
  • 解锁GIL
  • 重复上述步骤

两种线程管理

  • _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) # 保护主线程运行  让子线程执行完
     logging.info("end all at " + ctime())


 if __name__ == '__main__':
     main()

2.举例 打印日志 (使用_thread 加锁执行

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)执行

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()   //自行判断进程是否结束 否则阻塞
    logging.info("end all at " + ctime())


if __name__ == '__main__':
    main()

4.举例 打印日志 (使用类继承 Thread threading执行

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()  #自行判断进程是否结束 否则阻塞
    logging.info("end all at " + ctime())


if __name__ == '__main__':
    main()

课后延伸

了解 同步原语 ,例如 锁 、信号量

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容