一. 线程(threading模块)
线程是CPU的最小执行单位,进程: 资源单位
multiprocess模块完全模仿了threading模块的接口,二者在使用层面,有很大的相似性

1 import time 2 from threading import Thread 3 #多线程并发,是不是看着和多进程很类似 4 def func(n): 5 time.sleep(1) 6 print(n) 7 8 #并发效果,1秒打印出了所有的数字 9 for i in range(10): 10 t = Thread(target=func,args=(i,)) 11 t.start()
1. 线程的创建

1 from threading import Thread 2 import time 3 def sayhi(name): 4 time.sleep(2) 5 print('%s say hello' %name) 6 7 if __name__ == '__main__': 8 t=Thread(target=sayhi,args=('太白',)) 9 t.start() 10 print('主线程')

1 import time 2 from threading import Thread 3 class Sayhi(Thread): 4 def __init__(self,name): 5 super().__init__() 6 self.name=name 7 def run(self): 8 time.sleep(2) 9 print('%s say hello' % self.name) 10 11 12 if __name__ == '__main__': 13 t = Sayhi('太白') 14 t.start() 15 print('主线程')
2. 线程的方法

1 from threading import Thread 2 import time 3 def sayhi(name): 4 time.sleep(2) 5 print('%s say hello' %name) 6 7 if __name__ == '__main__': 8 t=Thread(target=sayhi,args=('太白',)) 9 t2=Thread(target=sayhi,args=('alex',)) 10 t.start() 11 t2.start() 12 t.join() #因为这个线程用了join方法,主线程等待子线程的运行结束 13 14 print('主线程') 15 print(t.is_alive()) #所以t这个线程肯定是执行结束了,结果为False 16 print(t2.is_alive()) #有可能是True,有可能是False,看子线程和主线程谁执行的快 17 ''' 18 egon say hello 19 主线程 20 False 21 '''

1 Thread实例对象的方法 2 # isAlive(): 返回线程是否活动的。 3 # getName(): 返回线程名。 4 # setName(): 设置线程名。 5 6 threading模块提供的一些方法: 7 # threading.currentThread(): 返回当前的线程变量。 8 # threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。 9 # threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果 10 11 12 from threading import Thread 13 import threading 14 from multiprocessing import Process 15 import os 16 17 def work(): 18 import time 19 time.sleep(3) 20 print(threading.current_thread().getName()) 21 22 if __name__ == '__main__': 23 #在主进程下开启线程 24 t=Thread(target=work) 25 t.start() 26 27 print(threading.current_thread())#主线程对象 28 print(threading.current_thread().getName()) #主线程名称 29 print(threading.current_thread().ident) #主线程ID 30 print(threading.get_ident()) #主线程ID 31 print(threading.enumerate()) #连同主线程在内有两个运行的线程 32 print(threading.active_count()) 33 print('主线程/主进程') 34 35 ''' 36 打印结果: 37 <_MainThread(MainThread, started 14104)> 38 MainThread 39 14104 40 14104 41 [<_MainThread(MainThread, started 14104)>, <Thread(Thread-1, started 17976)>] 42 2 43 主线程/主进程 44 Thread-1 45 '''
二. 线程和进程效率对比

1 from threading import Thread 2 from multiprocessing import Process 3 import os 4 import time 5 def work(): 6 print('hello') 7 8 if __name__ == '__main__': 9 s1 = time.time() 10 #在主进程下开启线程 11 t=Thread(target=work) 12 t.start() 13 t.join() 14 t1 = time.time() - s1 15 print('进程的执行时间:',t1) 16 print('主线程/主进程') 17 ''' 18 打印结果: 19 hello 20 进程的执行时间: 0.0 21 主线程/主进程 22 ''' 23 24 s2 = time.time() 25 #在主进程下开启子进程 26 t=Process(target=work) 27 t.start() 28 t.join() 29 t2 = time.time() - s2 30 print('线程的执行时间:', t2) 31 print('主线程/主进程') 32 ''' 33 打印结果: 34 hello 35 线程的执行时间: 0.5216977596282959 36 主线程/主进程 37 '''
三. 查看子线程和主线程是否在同一进程
# 查看子线程和主线程是否在同一个进程中 from threading import Thread import os def fun(): print('子线程的pid',os.getpid()) #获得当前 线程pid if __name__ == '__main__': t = Thread(target=fun,) t.start() print('主线程的pid',os.getpid()) #获得当前 pid
#结果是一样的,是同一进程里
四. 线程之间的数据是共享的
from threading import Thread def fun(): global a a -= 1 a = 10 if __name__ == '__main__': t = Thread(target=fun,) t.start() t.join() # 加join 等待t 结束 print(a) # 9 证明数据是共享的
五. 验证多线程共享资源造成的数据不安全
# 验证多线程共享资源造成的数据不安全的问题 from threading import Thread import time def fun(): global a t = a time.sleep(0.00001) t -= 1 a = t a = 20 if __name__ == '__main__': l = [] for i in range(20): t = Thread(target=fun,) l.append(t) t.start() for i in l : i.join() print(a) # 18
六. 加锁解决共享数据不安全的问题
锁(互斥锁同步锁) #Lock,解决数据共享是数据不安全的问题,
但同时也牺牲了效率

1 from threading import Thread,Lock 2 import time 3 def fun(l): 4 l.acquire() 5 global a 6 t = a 7 time.sleep(0.1) 8 t -= 1 9 a = t 10 l.release() 11 a = 20 12 if __name__ == '__main__': 13 l = [] 14 lock = Lock() 15 for i in range(20): 16 t = Thread(target=fun ,args=(lock,)) 17 l.append(t) 18 t.start() 19 for i in l: 20 i.join() 21 print(a)
七. 死锁现象
死锁现象: 双方互相等待对方释放对方手里拿到的那个锁

1 from threading import Thread ,Lock 2 import time 3 4 def fun1(lock_A,lock_B): 5 lock_A.acquire() 6 time.sleep(1) 7 8 print('A抢到了锁a') 9 lock_B.acquire() 10 print('A抢到了锁b') 11 lock_B.release() 12 lock_A.release() 13 def fun2(lock_A,lock_B): 14 lock_B.acquire() 15 print('B抢到了b锁') 16 lock_A.acquire() 17 print('B抢到了a锁') 18 lock_A.release() 19 lock_B.release() 20 if __name__ == '__main__': 21 lock_A = Lock() 22 lock_B = Lock() 23 t1 = Thread(target=fun1,args=(lock_A,lock_B)) 24 t2 = Thread(target=fun2,args=(lock_A,lock_B)) 25 t1.start() 26 t2.start()
八. 解决死锁, 使用递归锁
同样是互斥,里面存着个计数器
进程的死锁和线程的是一样的,而且一般情况下进程之间是数据不共享的,
不需要加锁,由于线程是对全局的数据共享的,所以对于全局的数据进行操作的时候,要加锁.

import time from threading import Thread,RLock fork_lock = noodle_lock = RLock() def eat1(name): noodle_lock.acquire() print('%s 抢到了面条'%name) fork_lock.acquire() print('%s 抢到了叉子'%name) print('%s 吃面'%name) fork_lock.release() noodle_lock.release() def eat2(name): fork_lock.acquire() print('%s 抢到了叉子' % name) time.sleep(1) noodle_lock.acquire() print('%s 抢到了面条' % name) print('%s 吃面' % name) noodle_lock.release() fork_lock.release() for name in ['taibai','wulaoban']: t1 = Thread(target=eat1,args=(name,)) t1.start() for name in ['alex','peiqi']: t2 = Thread(target=eat2,args=(name,)) t2.start()
九. 守护线程
守护线程: 主线程等着进程中所有非守护线程的结束,才算结束
守护进程: 主进程代码结束, 守护进程跟着结束

1 # 守护线程 2 from threading import Thread 3 import time 4 from multiprocessing import Process 5 6 def fun1(): 7 time.sleep(3) 8 print(111111111111) 9 def fun2(): 10 time.sleep(2) 11 print(222222222222) 12 if __name__ == '__main__': 13 # p1 = Process(target=fun1, ) 14 # p2 = Process(target=fun2, ) 15 # p2.daemon = True 16 # # p1.daemon = True 17 # p1.start() 18 # p2.start() 19 20 t1 = Thread(target=fun1,) 21 t2 = Thread(target=fun2,) 22 t2.daemon = True 23 # t1.daemon = True 24 t1.start() 25 t2.start() 26 27 28 print('结束')
十. 信号量

1 # 信号量 2 import time,random 3 from multiprocessing import Process,Semaphore 4 from threading import Thread,Semaphore 5 def fun(i,s): 6 s.acquire() 7 time.sleep(random.randint(1,3)) 8 print('%s号来了' %i) 9 s.release() 10 11 if __name__ == '__main__': 12 s = Semaphore(4) 13 for i in range(10): 14 t = Thread(target=fun,args=(i,s)) # 线程守护 15 t.start() 16 17 # s = Semaphore(4) 18 # for i in range(10): 19 # p = Process(target=fun,args=(i,s)) #进程守护 20 # p.start()
十一. 事件

1 from threading import Thread,Event 2 e = Event() #默认状态False 3 print(1) 4 e.set() #设置状态为True 5 print(e.is_set()) #查看状态 6 e.clear() # 设置状态 False 7 print(e.is_set()) #查看状态 8 e.set() #设置状态 9 print(e.is_set()) #查看状态 10 e.wait() #判断 等 False 走True 11 print('结束')