Python通过两个标准库thread和threading提供对线程的支持。thread提供了低级别的、原始的线程以及一个简单的锁。threading模块对thread进行了进一步的封装,因此在使用的时候,一般使用threading模块。
多任务可以由多进程完成,也可以由一个进程内的多线程完成。进程是由若干线程组成的,一个进程至少有一个线程。
1、使用threading模块创建线程
例:利用Thread类创建线程
与利用Process()创建进程类似,Thread()类的target函数接受一个函数,用于Thread类执行时调用,如果调用的函数需要参数,则通过args参数传递一个元组类型的参数列表。
例:调用带参数的函数
当需要一些复杂的逻辑时,直接用Thread()调用函数总显得有些复杂,我们可以利用Thread创建的子类满足需求。
2、使用Thread子类创建线程
例:利用Thread子类创建线程
我们自己创建的类,继承自Thread,当执行start()方法时,Python解释器会调用自定义类中重写的run()方法。
3、多个线程的执行顺序
当启动多个线程时,线程之间的执行是没有顺序的,线程之间的调度是由操作系统的调度算法来决定的。
例:启动多个线程
4、多个线程之间共享全局变量
多个进程之间是相互独立的,因此多个进程之间是不会共享全局变量的。但是多个线程之间会共享全局变量,当一个线程改变全局变量时,另一个线程中的全局变量会随之改变。
例:多线程之间共享全局变量
5、多个线程共享全局变量造成的问题
多个线程共享全局变量的优点是,不再像多个进程那样,如果要共享数据需要借助第三方才能够实现,比如Queue,但是如果处理不好多线程共享全局变量,会发生意想不到的结果。
例:多个线程共享全局变量造成的问题
6、解决多线程共享全局变量BUG
我们可以定义另一个全局变量,来判断当前线程的状态,只有当一个线程执行完之后,另一个线程才能开启。
例:定义线程是否执行完标记
由以上程序可知,定义了判断线程结束标记以后,虽然能够解决问题,但是当第一个线程执行时,第二个线程在循环判断标记是否已经改变,循环判断会占用CPU资源,对性能造成影响。
7、利用互斥锁
某个线程要共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进入写入操作,从而保证了多线程情况下数据的正确性。
创建锁
mutex=threading.Lock()
锁定
mutex.acquire([blocking])#里面可以加blocking(等待的时间)或者不加,不加就会一直等待(堵塞)
释放
mutex.release()
只要一上锁,由多任务变为单任务,相当于只有一个线程在运行。