Python多线程编程之threading模块详解

一、介绍

线程是什么?线程有啥用?线程和进程的区别是什么?

线程是操作系统能够进行运算调度的最小单位。被包含在进程中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

二、python如何创建线程

2.1 方法一:

创建Thread对象

步骤:

1.目标函数

2.实例化Thread对象

3.调用start()方法


import threading# 目标函数1def fun1(num):    for i in range(num):        print('线程1: 第%d次循环:' % i)# 目标函数2def fun2(lst):    for ele in lst:        print('线程2: lst列表中元素 %d' % ele)def main():    num = 10    # 实例化Thread对象    # target参数一定为一个函数,且不带括号    # args参数为元组类型,参数为一个时一定要加逗号    t1 = threading.Thread(target=fun1, args=(num,))    t2 = threading.Thread(target=fun2, args=([1, 2, 3, 4, 5],))    # 调用start方法    t1.start()    t2.start()if __name__ == '__main__':    main()

2.2 方法二:

创建子类继承threading.Thread类

import threadingimport osclass Person(threading.Thread):    def run(self):        self.sing(5)        self.cook()    @staticmethod    def sing(num):        for i in range(num):            print('线程[%d]: The person sing %d song.' % (os.getpid(), i))    @staticmethod    def cook():        print('线程[%d]:The person has cooked breakfast.' % os.getpid())def main():    p1 = Person()    p1.start()    p2 = Person()    p2.start()if __name__ == '__main__':    main()

三、线程的用法

3.1 确定当前的线程

import threadingimport timeimport loggingdef fun1():    print(threading.current_thread().getName(), 'starting')    time.sleep(0.2)    print(threading.current_thread().getName(), 'exiting')def fun2():    # print(threading.current_thread().getName(), 'starting')    # time.sleep(0.3)    # print(threading.current_thread().getName(), 'exiting')    logging.debug('starting')    time.sleep(0.3)    logging.debug('exiting')logging.basicConfig(    level=logging.DEBUG,    format='[%(levelname)s] (%(threadName)-10s) %(message)s')def main():    t1 = threading.Thread(name='线程1', target=fun1)    t2 = threading.Thread(name='线程2', target=fun2)    t1.start()    t2.start()if __name__ == '__main__':    main()

3.2 守护线程

区别

  •  普通线程:主线程等待子线程关闭后关闭
  • 守护线程:管你子线程关没关,主线程到时间就关闭

守护线程如何搞

  • 方法1:构造线程时传入dameon=True
  • 方法2:调用setDaemon()方法并提供参数True
import threadingimport timeimport loggingdef daemon():    logging.debug('starting')    # 添加延时,此时主线程已经退出,exiting不会打印    time.sleep(0.2)    logging.debug('exiting')def non_daemon():    logging.debug('starting')    logging.debug('exiting')logging.basicConfig(    level=logging.DEBUG,    format='[%(levelname)s] (%(threadName)-10s) %(message)s')def main():    # t1 = threading.Thread(name='线程1', target=daemon)    # t1.setDaemon(True)    t1 = threading.Thread(name='线程1', target=daemon, daemon=True)    t2 = threading.Thread(name='线程2', target=non_daemon)    t1.start()    t2.start()    # 等待守护线程完成工作需要调用join()方法,默认情况join会无限阻塞,可以传入浮点值,表示超时时间    t1.join(0.2)    t2.join(0.1)if __name__ == '__main__':    main()

3.3 控制资源访问

目的:

python线程中资源共享,如果不对资源加上互斥锁,有可能导致数据不准确。

import threadingimport timeg_num = 0def fun1(num):    global g_num    for i in range(num):        g_num += 1    print('线程1 g_num = %d' % g_num)def fun2(num):    global g_num    for i in range(num):        g_num += 1    print('线程2 g_num = %d' % g_num)def main():    t1 = threading.Thread(target=fun1, args=(1000000,))    t2 = threading.Thread(target=fun1, args=(1000000,))    t1.start()    t2.start()if __name__ == '__main__':    main()    time.sleep(1)    print('主线程 g_num = %d' % g_num)

互斥锁

import threadingimport timeg_num = 0L = threading.Lock()def fun1(num):    global g_num    L.acquire()    for i in range(num):        g_num += 1    L.release()    print('线程1 g_num = %d' % g_num)def fun2(num):    global g_num    L.acquire()    for i in range(num):        g_num += 1    L.release()    print('线程2 g_num = %d' % g_num)def main():    t1 = threading.Thread(target=fun1, args=(1000000,))    t2 = threading.Thread(target=fun1, args=(1000000,))    t1.start()    t2.start()if __name__ == '__main__':    main()    time.sleep(1)    print('主线程 g_num = %d' % g_num)

互斥锁引发的另一个问题:死锁

死锁产生的原理:

在这里插入图片描述

import threadingimport timeg_num = 0L1 = threading.Lock()L2 = threading.Lock()def fun1():    L1.acquire(timeout=5)    time.sleep(1)    L2.acquire()    print('产生死锁,并不会打印信息')    L2.release()    L1.release()def fun2():    L2.acquire(timeout=5)    time.sleep(1)    L1.acquire()    print('产生死锁,并不会打印信息')    L1.release()    L2.release()def main():    t1 = threading.Thread(target=fun1)    t2 = threading.Thread(target=fun2)    t1.start()    t2.start()if __name__ == '__main__':    main()    time.sleep(1)    print('主线程 g_num = %d' % g_num)

如何避免产生死锁:

锁超时操作

import threadingimport timeg_num = 0L1 = threading.Lock()L2 = threading.Lock()def fun1():    L1.acquire()    time.sleep(1)    L2.acquire(timeout=5)    print('超时异常打印信息1')    L2.release()    L1.release()def fun2():    L2.acquire()    time.sleep(1)    L1.acquire(timeout=5)    print('超时异常打印信息2')    L1.release()    L2.release()def main():    t1 = threading.Thread(target=fun1)    t2 = threading.Thread(target=fun2)    t1.start()    t2.start()if __name__ == '__main__':    main()    time.sleep(1)    print('主线程 g_num = %d' % g_num)

到此这篇关于python多线程编程之threading模块详解的文章就介绍到这了,更多相关python threading模块内容请搜索 以前的文章或继续浏览下面的相关文章希望大家以后多多支持 !

相关文章

发表新评论