1、什么是线程
进程其实不是一个执行单位,进程是一个资源单位
每个进程内自带一个线程,线程才是CPU上的执行单位
如果把操作系统比喻为一座工厂
在工厂内每造出一个车间===》启动一个进程
每个车间内至少有一条流水线===》每个进程内至少有一个线程
线程==》单指代码的执行过程
进程==》资源的申请与销毁的过程
2、进程VS线程
1)内存共享or隔离
多个进程内存空间彼此隔离
同一进程下的多个线程共享该进程内的数据
2)创建速度
造线程的速度要远远快于造进程
一、开启线程的两种方式(重点)
方式一:导入Thread模块
1 from threading importThread2 importtime3
5 deftask(name):6 print('%s is running' %name)7 time.sleep(3)8 print('%s is done' %name)9 if __name__ == '__main__':10 t=Thread(target=task,args=('子线程',))11 t.start()12 print('主')
方式二:创建类继承Thread
1 from threading importThread2 importtime3
4
6 #class Mythread(Thread):
7 #def run(self):
8 #print('%s is running' %self.name)
9 #time.sleep(3)
10 #print('%s is done' %self.name)
11 #12 #if __name__ == '__main__':
13 #t=Mythread()
14 #t.start()
15 #print('主')
二、线程VS进程(重点)
1 #from threading import Thread
2 #from multiprocessing import Process
3 #import time
4 #5 #def task(name):
6 #print('%s is running' %name)
7 #time.sleep(3)
8 #print('%s is done' %name)
9 #10 #if __name__ == '__main__':
11 #t=Thread(target=task,args=('子线程',))
12 ## t=Process(target=task,args=('子进程',))
13 #t.start()
14 #print('主')
线程运行结果:
进程运行结果:
2)同一进程下的多个线程共享该进程内的数据(了解知识点)
1 #from threading import Thread
2 #import time
3 #4 #x=100
5 #def task():
6 #global x
7 #x=0
8 #9 #if __name__ == '__main__':
10 #t=Thread(target=task,)
11 #t.start()
12 ## time.sleep(3)
13 #t.join()
14 #print('主',x)
View Code
3)查看pid(了解知识点)
注意:一个进程中的子线程pid相同
1 from threading importThread2 importtime,os3
4 deftask():5 print(os.getpid())6
7 if __name__ == '__main__':8 t=Thread(target=task,)9 t.start()10 print('主',os.getpid())
View Code
三、线程对象的其他方法和属性(熟悉知识点)
1)主进程等子进程是因为主进程要给子进程收尸
2)进程必须等待其内部所有线程都运行完毕才结束
1 #from threading import Thread
2 #import time
3 #4 #def task(name):
5 #print('%s is running' %name)
6 #time.sleep(3)
7 #print('%s is done' %name)
8 #if __name__ == '__main__':
9 #t=Thread(target=task,args=('子线程',))
10 #t.start()
11 #print('主')
12 #
View Code
1 from threading importThread,current_thread,active_count,enumerate2 importtime3
4
5 deftask():6 print('%s is running' %current_thread().name)7 time.sleep(3)8 print('%s is done' %current_thread().name)9
10
11 if __name__ == '__main__':12 t = Thread(target=task,name='xxx')13 t.start()14 #t.join()
15 #print(t.is_alive())
16 #print(t.getName())
17 #print(t.name)
18 #print('主',active_count())
19 #print(enumerate())
20
21 #t.join()
22 current_thread().setName('主线程')23 print('主',current_thread().name)
View Code
四、守护线程(熟悉知识点)
守护线程(daemon)会在本进程内所有非守护的线程都死掉了才跟着死
即:
守护线程其实守护的是整个进程的运行周期(进程内所有的非守护线程都运行完毕)
1 #from threading import Thread,current_thread
2 #import time
3 #4 #5 #def task():
6 #print('%s is running' % current_thread().name)
7 #time.sleep(3)
8 #print('%s is done' % current_thread().name)
9 #10 #11 #if __name__ == '__main__':
12 #t = Thread(target=task,name='守护线程')
13 #t.daemon=True
14 #t.start()
15 #print('主')
守护进程
1 from threading importThread2 importtime3 deffoo():4 print(123)5 time.sleep(3)6 print("end123")7
8 defbar():9 print(456)10 time.sleep(1)11 print("end456")12
13
14 t1=Thread(target=foo)15 t2=Thread(target=bar)16
17 t1.daemon=True18 t1.start()19 t2.start()20 print("main-------")21
22 '''
23 12324 45625 main-------26 end45627
28 '''
较迷惑人的守护进程
五、互斥锁(熟悉知识点)
1 from threading importThread,Lock2 importtime3
4 mutex=Lock()5
6 x=100
7 deftask():8 globalx9 #mutex.acquire()
10 temp=x11 time.sleep(0.1)12 x=temp-1
13 #mutex.release()
14
15 if __name__ == '__main__':16 t_l=[]17 start=time.time()18 for i in range(100):19 t=Thread(target=task)20 t_l.append(t)21 t.start()22
23 for t int_l:24 t.join()25
26 stop=time.time()27 print(x,stop-start)
互斥锁
六、死锁现象与递归锁(熟悉知识点)
如果用Lock(互斥锁),会发生死锁现象
递归锁本质是一把锁,可连续acqruie,但只有其上的计数为0时其他线程才可对其调用
1 from threading importThread,Lock,active_count,RLock2 importtime3
4 #mutexA=Lock()
5 #mutexB=Lock()
6 obj=RLock() #递归锁的特点:可以连续的acquire
7 mutexA=obj8 mutexB=obj9
10 classMythread(Thread):11 defrun(self):12 self.f1()13 self.f2()14
15 deff1(self):16 mutexA.acquire()17 print('%s 拿到A锁' %self.name)18
19 mutexB.acquire()20 print('%s 拿到B锁' %self.name)21 mutexB.release()22
23 mutexA.release()24
25 deff2(self):26 mutexB.acquire()27 print('%s 拿到B锁' %self.name)28 time.sleep(1)29
30 mutexA.acquire()31 print('%s 拿到A锁' %self.name)32 mutexA.release()33
34 mutexB.release()35
36 if __name__ == '__main__':37 for i in range(10):38 t=Mythread()39 t.start()40 #print(active_count())
View Code
七、信号量(熟悉知识点)
信号量本质上还是锁,但区别信号量是控制同一时刻并发执行的任务数
1 from threading importThread,Semaphore,current_thread2 importtime,random3
4 sm=Semaphore(5)5
6 deftask():7 with sm:8 print('%s 正在上厕所' %current_thread().name)9 time.sleep(random.randint(1,4))10
11
12 if __name__ == '__main__':13 for i in range(20):14 t=Thread(target=task)15 t.start()
信号量