线程的概念
线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务,在单个程序中同时运行多个线程完成不同的工作,称为多线程
进程的概念
进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元。
线程和进程的区别
进程间是独立的,这表现在内存空间,上下文环境;线程运行在进程空间内。 一般来讲进程是无法突破进程边界存取其他进程内的存储空间;而线程由于处于进程空间内,所以同一进程所产生的线程共享同一内存空间。 同一进程中的两段代码不能够同时执行,除非引入线程。 线程是属于进程的,当进程退出时该进程所产生的线程都会被强制退出并清除。 线程占用的资源要少于进程所占用的资源。 进程和线程都可以有优先级。 在线程系统中进程也是一个线程。可以将进程理解为一个程序的第一个线程。
线程的调用方式
直接调用
1 import threading 2 import time 3 def haha(num): 4 print("running thread:%s" %num) 5 time.sleep(3) 6 7 if __name__ == "__main__": 8 t1 = threading.Thread(target=haha,args=(1,)) #生成一个线程实例,执行sayhi,参数args 9 t2 = threading.Thread(target=haha,args=(2,)) #生成另一个线程实例 10 11 t1.start() #启动线程 12 t2.start() #启动另一个线程 13 14 print(t1.getName()) #获取线程名 15 print(t2.getName())
间接调用
1 import threading 2 import time 3 4 class MyThread(threading.Thread): 5 def __init__(self,num): 6 threading.Thread.__init__(self) 7 self.num = num 8 9 def run(self): #定义每个线程要运行的函数,必须是run 10 print("running thread:%s" %self.num) 11 time.sleep(3) 12 13 if __name__ == "__main__": 14 t1 = MyThread(1) 15 t2 = MyThread(2) 16 t1.start() 17 t2.start()
循环生成10个线程
1 import threading 2 import time 3 4 def sayhi(num): #定义每个线程要运行的函数 5 print("running on number:%s" %num) 6 time.sleep(3) 7 8 if __name__ == '__main__': 9 t_list = [] 10 for i in range (10): 11 t = threading.Thread(target=sayhi,args=[i,]) 12 t.start() 13 t_list.append(t) 14 for i in t_list: 15 i.join() 16 print('---main---')
join,等待线程执行完
1 import threading 2 import time 3 4 def sayhi(num): #定义每个线程要运行的函数 5 print("running on number:%s" %num) 6 time.sleep(3) 7 8 if __name__ == '__main__': 9 10 t1 = threading.Thread(target=sayhi,args=(1,)) #生成一个线程实例 11 t2 = threading.Thread(target=sayhi,args=(2,)) #生成另一个线程实例 12 13 t1.start() #启动线程 14 t2.start() #启动另一个线程 15 16 print(t1.getName()) #获取线程名 17 print(t2.getName()) 18 19 t1.join() #t1.wait() 等待线程执行完 20 t2.join() #t2.wait() 21 22 print('---main---') #等线程执行完打印,如果不加join,会同线程执行的同时打印
setDaemon(守护线程)
1 import time 2 import threading 3 4 def run(n): 5 6 print('[%s]------running---- ' % n) 7 time.sleep(2) 8 print('--done--') 9 10 def main(): 11 for i in range(5): 12 t = threading.Thread(target=run,args=[i,]) 13 t.start() 14 print('starting thread', t.getName()) 15 16 17 m = threading.Thread(target=main,args=[]) 18 m.setDaemon(True) #将主线程设置为Daemon线程,它退出时,其它子线程会同时退出,不管是否执行完任务 19 m.start() 20 print("---main thread done----")
线程锁
生成100个线程,去修改一个公共变量num=100,每次进行减一操作,最后结果应该等于0,但事实并非如此,由于两个线程是并发同时运行,所以两个线程可能会取得同一个数进行操作,如,前两个线程可能同时取得100,对其减一,结果为99,并非是98。
1 import time 2 import threading 3 4 def addNum(): 5 global num #在每个线程中都获取这个全局变量 6 print('--get num:',num ) 7 time.sleep(1) 8 num -=1 #对此公共变量进行-1操作 9 10 num = 100 #设定一个共享变量 11 thread_list = [] 12 for i in range(100): 13 t = threading.Thread(target=addNum) 14 t.start() 15 thread_list.append(t) 16 17 for t in thread_list: #等待所有线程执行完毕 18 t.join() 19 20 print('final num:', num )
添加线程锁,线程在操作公共变量时对其加锁,使其他线程无法修改,待该线程对其修改完,再对其进行解锁
1 import time 2 import threading 3 4 def addNum(): 5 global num #在每个线程中都获取这个全局变量 6 print('--get num:',num ) 7 time.sleep(1) 8 lock.acquire() #修改数据前加锁 9 num -=1 #对此公共变量进行-1操作 10 lock.release() #修改后解锁 11 12 num = 100 #设定一个共享变量 13 thread_list = [] 14 lock = threading.Lock() #生成全局锁 15 for i in range(100): 16 t = threading.Thread(target=addNum) 17 t.start() 18 thread_list.append(t) 19 20 for t in thread_list: #等待所有线程执行完毕 21 t.join() 22 23 print('final num:', num )
递归锁
1 import threading,time 2 3 def run1(): 4 print("grab the first part data") 5 lock.acquire() 6 global num 7 num +=1 8 lock.release() 9 return num 10 def run2(): 11 print("grab the second part data") 12 lock.acquire() 13 global num2 14 num2+=1 15 lock.release() 16 return num2 17 def run3(): 18 lock.acquire() 19 res = run1() 20 print('--------between run1 and run2-----') 21 res2 = run2() 22 lock.release() 23 print(res,res2) 24 25 26 if __name__ == '__main__': 27 28 num,num2 = 0,0 29 lock = threading.RLock() 30 for i in range(10): 31 t = threading.Thread(target=run3) 32 t.start() 33 34 while threading.active_count() != 1: 35 print(threading.active_count()) 36 else: 37 print('----all threads done---') 38 print(num,num2)
Semaphore(信号量)
多个线程同时运行
1 import threading,time 2 3 def run(n): 4 semaphore.acquire() 5 time.sleep(1) 6 print("run the thread: %s " %n) 7 semaphore.release() 8 9 if __name__ == '__main__': 10 11 num= 0 12 semaphore = threading.BoundedSemaphore(3) #最多允许3个线程同时运行 13 for i in range(20): 14 t = threading.Thread(target=run,args=(i,)) 15 t.start() 16 17 while threading.active_count() != 1: 18 pass #print threading.active_count() 19 else: 20 print('----all threads done---') 21 print(num)
Events
线程间交互,生成三辆车和一个红灯,实现红灯停绿灯行的功能
1 import threading,time 2 import random 3 def light(): 4 if not event.isSet(): 5 event.set() #wait就不阻塞 #绿灯状态 6 count = 0 7 while True: 8 if count < 10: 9 print('