一:线程
线程(有时候称为轻量级进程),线程包括开始、执行顺序和结束三部分。它有一个指令指针,用于记录当前运行的上下文。当其他线程运行时,它可以被抢占(中断)和临时挂起(也称为睡眠)--这种做法叫做让步
一个进程中的各个线程与主线程共享同一片数据空间,因此相比与独立的进程而言,线程间的信息共享和通信更加容易。线程一般是以并发方式执行的,正是由于这种并行和数据共享机制,使得多任务间的协作成为可能。当然,在单核CPU系统中,因为真正的并发是不可能的,所以线程的执行实际上是这样规划的:每个线程运行一小会儿,然后让步给其他线程(再次排队等待更多的CPU时间)。在整个进程的执行的过程中,每个线程执行他自己特定任务,在必要时和其他线程进行结果通信。
当然,这种共享并不是没有风险的。如果两个或多个线程访问同一片数据,由于数据访问顺序不同,可能导致结果不一致,这种情况通常称为竞态条件。
另外,线程无法给予公平的执行时间。
尽管python解释器中可以运行多个线程,但是在任意给定时刻只有一个线程会被解释器执行
二:使用线程的第一种方式:
1 import time 2 from threading import Thread 3 4 def test(): 5 print(‘-----多线程-------‘) 6 time.sleep(1) 7 for i in range(5): 8 t = Thread(target=test) #创建一个线程,参数是要执行的函数 9 t.start() #启动线程
t.join()# 保证等待子线程运行完再执行后续的主线程
三:使用线程的第二种方式:
1 #使用多线程的第二种方式(创建一个类继承Thread类,重写run()方法) 2 import threading 3 import time 4 class MyThread(threading.Thread): 5 def run(self): 6 for i in range(5): 7 print(‘-----使用多线程的第二种方式------‘) 8 time.sleep(1) 9 if __name__ == ‘__main__‘: 10 m = MyThread() 11 m.start()
四:加互斥锁解决多线程之间共享数据被修改出现的异常数据
说明:
当多个线程几乎同时访问一个共享数据时,需要进行同步控制
线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制就是引入互斥锁。
互斥锁为资源引入一个状态:锁定/非锁定
某个线程要更改共享数据时,先将其锁定,此时资源的状态为”锁定“,其他线程不能更改;直到改线程释放资源,将资源状态变成”非锁定“,其他线程才能再次锁定改资源,互斥锁保证了每次只有线程进行写入操作,从而保证了多线程情况下数据的准确性。
示例代码:
1 from threading import Thread,Lock 2 num = 0 3 def test1(lock): 4 global num 5 lock.acquire() #上锁 6 for i in range(1000000): 7 num += 1 8 lock.release() #释放锁(解锁) 9 print(‘----test1---%d‘%num) 10 def test2(lock): 11 global num 12 lock.acquire() 13 for i in range(1000000): 14 num += 1 15 lock.release() 16 print(‘-----test2-----%d‘%num) 17 def main(): 18 lock =Lock()#初始化一个互斥锁对象 19 t1 = Thread(target=test1,args=(lock,)) #创建一个多线程 20 t1.start() 21 t1.join() 22 t2 = Thread(target=test2,args=(lock,)) 23 t2.start() 24 t2.join()#等待子线程执行完成后再继续主线程 25 print(num) 26 27 if __name__ == ‘__main__‘: 28 main()
运行结果:
----test1---1000000 -----test2-----2000000 2000000