多线程
并发:指的是任务数多余cpu核数,通过操作系统的各种任务调度算法,实现用多个任务“一起”执行(实际上总有一些任务不在执行,因为切换任务的速度相当快,看上去一起执行而已)
并行:指的是任务数小于等于cpu核数,即任务真的是一起执行的
1、多线程执行:
import threading import time def say(): print('jjjjj') time.sleep(1) def main(): for i in range(10): t = threading.Thread(target=say) t.start() if __name__ =='__main__': main()
说明:当调用star()时,才会真正创建线程,并开始执行
2、线程执行代码的封装
使用threading模块时,往往会定义一个新的子类,class,只要继承threading.Thread,然后从写run方法
#coding=utf-8 import threading import time class MyTread(threading.Thread): def run(self): for i in range(5): time.sleep(1) msg = "I'm "+self.name+' @ '+str(i) print(msg) if __name__ == '__main__': t = MyTread() t.start()
说明:python的threading.Thread类中有一个run方法,用于定义线程的功能函数可以在自己的线程类中覆盖该方法。而创建自己的线程实例后,通过Thread类中的start()方法。启动该线程,当该线程获得执行的机会时,就会调用run方法执行线程
3、多线程共享全局变量:
在一个进程内的所有线程共享全局变量,很方便在多个线程间共享数据
缺点就是,线程是对全局变量随意遂改可能造成多线程之间对全局变量的混乱(即线程非安全)
from threading import Thread import time def test1(): for i in range(5): global g_num g_num +=1 print(g_num) def test2(): print('------test2,%d'%g_num) if __name__ == '__main__': g_num = 0 t1 = Thread(target=test1) t1.start() t2 = Thread(target=test2) t2.start() time.sleep(10) print(g_num)
4、互斥锁:
某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性
# 创建锁 mutex = threading.Lock() # 锁定 mutex.acquire() # 释放 mutex.release()
如果这个锁之前是没有上锁的,那么acquire不会堵塞
如果在调用acquire对这个锁上锁之前 它已经被 其他线程上了锁,那么此时acquire会堵塞,直到这个锁被解锁为止
示例:
import time import threading def test1(): global g_num for i in range(5): mutex.acquire() # 上锁 g_num += 1 print('----jj-----',g_num) mutex.release() # 解锁 print('-----test1----',g_num) time.sleep(1) def test2(): global g_num mutex.acquire() g_num += 10 mutex.release print('----test2---',g_num) time.sleep(1) if __name__ == '__main__': g_num = 0 # 创建互斥锁 mutex = threading.Lock() # 创建线程 t1 = threading.Thread(target=test1) t1.start() t2 = threading.Thread(target=test2) t2.start()