1.线程是程序执行的最小单位,而进程是操作系统分配资源的最小单位
2.一个进程是由一个或多个线程组成,线程是一个进程中代码不同的执行路线
3.进程之间相互独立,但同一进程下的各个线程之间共享程序的内存空间(如代码段、数据集、堆等)及一些进程级的资源(如打开文件和信号等)
函数式:调用 _thread 模块中的start_new_thread()函数来产生新线程。语法如下:
_thread.start_new_thread ( function, args[, kwargs] )
参数说明:
function - 线程函数。
args - 传递给线程函数的参数,他必须是个tuple类型。
kwargs - 可选参数。
实例
import threading import time def test(x): start_time = time.time() print(x) time.sleep(3) print(f"test()函数一共运行了{time.time() - start_time}秒\n") # test(2) # test(3) t1 = threading.Thread(target=test,args=(3,)) t2 =threading.Thread(target=test,args=(6,)) t1.start() t2.start()
结果
3 6 test()函数一共运行了3.002709150314331秒 test()函数一共运行了3.002709150314331秒
threading 模块除了包含 _thread 模块中的所有方法外,还提供的其他方法:
threading.currentThread():
返回当前的线程变量。
threading.enumerate():
返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
threading.activeCount():
返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
除了使用方法外,线程模块同样提供了Thread类来处理线程,Thread类提供了以下方法:
run():
用以表示线程活动的方法。
start():
启动线程活动。
join([time]):
等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。
isAlive():
返回线程是否活动的。
getName():
返回线程名。
setName():
设置线程名。
实例
import threading import time class MyThread(threading.Thread): def __init__(self,n): super(MyThread,self).__init__() self.n = n def run(self): print("以线程类的方式创建多线程",self.n) t1 = MyThread(1) t2 = MyThread(2) t1.start() t2.start()
结果
以线程类的方式创建多线程 1 以线程类的方式创建多线程 2
如果多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性,需要对多个线程进行同步。
使用Thread对象的Lock
和Rlock
可以实现简单的线程同步,这两个对象都有acquire
方法和release
方法,对于那些需要每次只允许一个线程操作的数据,可以将其操作放到acquire和release方法之间。
多线程的优势在于可以同时运行多个任务(至少感觉起来是这样)。但是当线程需要共享数据时,可能存在数据不同步的问题。
考虑这样一种情况:一个列表里所有元素都是0,线程"set"从后向前把所有元素改成1,而线程"print"负责从前往后读取列表并打印。
那么,可能线程"set"开始改的时候,线程"print"便来打印列表了,输出就成了一半0一半1,这就是数据的不同步。为了避免这种情况,引入了锁的概念。
锁有两种状态——锁定和未锁定。每当一个线程比如"set"要访问共享数据时,必须先获得锁定;如果已经有别的线程比如"print"获得锁定了,那么就让线程"set"暂停,也就是同步阻塞;等到线程"print"访问完毕,释放锁以后,再让线程"set"继续。
经过这样的处理,打印列表时要么全部输出0,要么全部输出1,不会再出现一半0一半1的尴尬场面。
实例
import threading def run(): global x lock.acquire() x += 1 lock.release() if __name__ == '__main__': x = 0 l1 = [] lock = threading.Lock() for i in range(100): t = threading.Thread(target=run()) t.start() l1.append(t) for t in l1: t.join() print(x)
结果
100 Process finished with exit code 0