Python中的多线程

Posted huyingsakai

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python中的多线程相关的知识,希望对你有一定的参考价值。

1、什么是线程

  进程其实不是一个执行单位,进程是一个资源单位

  每个进程内自带一个线程,线程才是CPU上的执行单位

  

如果把操作系统比喻为一座工厂

  在工厂内每造出一个车间===》启动一个进程

  每个车间内至少有一条流水线===》每个进程内至少有一个线程

线程==》单指代码的执行过程

进程==》资源的申请与销毁的过程

 

2、进程VS线程

  1)内存共享or隔离

    多个进程内存空间彼此隔离

    同一进程下的多个线程共享该进程内的数据

  2)创建速度

    造线程的速度要远远快于造进程

 

一、开启线程的两种方式(重点)


方式一:导入Thread模块

1
from threading import Thread 2 import time 3 5 def task(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 import Thread 2 import time 3 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 import Thread
 2 import time,os
 3 
 4 def task():
 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 import Thread,current_thread,active_count,enumerate
 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=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 import Thread
 2 import time
 3 def foo():
 4     print(123)
 5     time.sleep(3)
 6     print("end123")
 7 
 8 def bar():
 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=True
18 t1.start()
19 t2.start()
20 print("main-------")
21 
22 ‘‘‘
23 123
24 456
25 main-------
26 end456
27 
28 ‘‘‘
较迷惑人的守护进程

五、互斥锁(熟悉知识点)

技术分享图片
 1 from threading import Thread,Lock
 2 import time
 3 
 4 mutex=Lock()
 5 
 6 x=100
 7 def task():
 8     global x
 9     # mutex.acquire()
10     temp=x
11     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 in t_l:
24         t.join()
25 
26     stop=time.time()
27     print(x,stop-start)
互斥锁

六、死锁现象与递归锁(熟悉知识点)

  如果用Lock(互斥锁),会发生死锁现象

  递归锁本质是一把锁,可连续acqruie,但只有其上的计数为0时其他线程才可对其调用

技术分享图片
 1 from threading import Thread,Lock,active_count,RLock
 2 import time
 3 
 4 # mutexA=Lock()
 5 # mutexB=Lock()
 6 obj=RLock() #递归锁的特点:可以连续的acquire
 7 mutexA=obj
 8 mutexB=obj
 9 
10 class Mythread(Thread):
11     def run(self):
12         self.f1()
13         self.f2()
14 
15     def f1(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     def f2(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 import Thread,Semaphore,current_thread
 2 import time,random
 3 
 4 sm=Semaphore(5)
 5 
 6 def task():
 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()
信号量

 



以上是关于Python中的多线程的主要内容,如果未能解决你的问题,请参考以下文章

PySide 中的多线程提升 Python C++ 代码

python中的多线程

Python中的多处理与线程

python并发编程中的多进程(代码实现)

Python中的多线程

122 Python程序中的多进程和多线程