首页 > 代码库 > 并发编程/GIL

并发编程/GIL

进程:

进程就是一个程序在一个数据集上的一次动态执行过程。进程一般由程序、数据集、进程控制块三部分组成。我们编写的程序用来描述进程要完成哪些功能以及如何完成;数据集则是程序在执行过程中用它来控制和管理进程,它是系统感知进程存在的唯一标识。

为了实现多道技术,使CPU使用率更高,系统会经常进行进行间的切换,切换会发生在出现IO操作的时候,以及系统固定时间的切换。

线程:

线程的出现是为了降低上下文切换的消耗,提高系统的并发性,并突破一个进程只能干一样事的缺陷,使到进程内并发成为可能。线程也叫轻量级进程,它是一个基本的CPU执行单元,也是程序执行过程中的最小单元,由线程ID、程序计数器、寄存器集合和堆栈共同组成。线程的引入减小了程序并发执行时的开销,提高了操作系统的并发性能。线程没有自己的系统资源。

 

进程与线程的关系:

1.一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。

2.资源分配给进程,同一进程的所有线程共享进程的所有资源。

3.CPU分给线程,即真正在CPU上进行的是线程。
Pyhon的多线程:由于GIL导致同一时刻同一进程只能有一个线程。

并行和并发:

并行处理(Parallel Processing)是计算机系统中能同时执行两个或更多个处理的一种计算方法。并行处理可同时工作于同一程序的不同方面。并行处理的主要目的是节省大型和复杂问题的解决时间。并发处理(concurrency Processing):指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机(CPU)上运行,但任一个时刻点上只有一个程序在处理机(CPU)上运行

并发的关键是你有处理多个任务的能力,不一定要同时。并行的关键是你有同时处理多个任务的能力。所以说,并行是并发的子集

 

threading模块

线程对象的创建:

thread直接创建:

 

 1  1 import time
 2  2 import threading
 3  3 def tingge():
 4  4      print(听歌)
 5  5      time.sleep(3)
 6  6      print(听歌结束)
 7  7 
 8  8 def xieboke():
 9  9      print(写博客)
10 10      time.sleep(5)
11 11      print(写博客结束)
12 12 
13 13 t1 = threading.Thread(target = tingge) #生成线程实例,target=函数名,args = 函数需要传参的参数,默认可以不传
14 14 t2 = threading.Thread(target = xieboke)
15 15 
16 16 t1.start()    #启动进程
17 17 t2.start()
18 18 print("ending!")
19 
20 
21 #继承Thread式自定义创建:
22 import threading
23 import time
24 class MyThread(threading.Thread):
25      
26      def __init__(self,num):
27           threading.Threa.__init__(self)
28           self.num = num
29      def run(self):
30           print("running on number:%s" % self.num )
31           time.sleep(3)
32 
33 t1 = MyThread(56)
34 t2 = MyThread(78)
35 
36 t1.start() 
37 t2.start()
38 print(ending)

 

 

 

以上第一段代码就实现了一个并发的效果。tingge与xieboke函数(子线程)跟主逻辑“print(‘ending!‘)”(主线程)同时启动,先几乎同时执行【print(‘听歌‘)、print(‘写博客‘)、print("ending!")】随后IO操作“sleep”,等3S听歌结束,再等2S写博客结束。如果使用串行的方法,程序全部执行则一共需要差不多8S的时间,降低了CPU的使用效率。

Threading的方法:

join:在子线程完成运行之前,这个子线程的父线程将一直被阻塞。

setDaemon:

 ‘‘‘
         将线程声明为守护线程,必须在start() 方法调用之前设置,如果不设置为守护线程程序会被无限挂起。

         当我们在程序运行中,执行一个主线程,如果主线程又创建一个子线程,主线程和子线程 就分兵两路,分别运行,那么当主线程完成

         想退出时,会检验子线程是否完成。如果子线程未完成,则主线程会等待子线程完成后再退出。但是有时候我们需要的是只要主线程

         完成了,不管子线程是否完成,都要和主线程一起退出,这时就可以 用setDaemon方法啦‘‘‘

这么看来,是不是当要执行多个线程,是不是都可以用Threading来解决呢?
其实并不是,对于计算密集型任务,Python的多线程并没有用。由于GIL的存在在,一个线程拥有了解释器的访问权之后,其他的所有线程都必须等待它释放解释器的访问权,即使这些线程的下一条指令并不会互相影响。
因此Python并不能达到一个并发的效果,同一时间只能运行一个线程,所以对于计算密集型任务,多个线程同时启动,CPU就需要频繁的来回切换,这样就加入了大量的切换时间。而串行的方式则只需要切换少数的几次,
因此对于计算密集型任务,Python的多线程并没有用,而对于上面的IO密集型任务,Python的多线程是有意义的。

那么Python有没有使用多核的方法呢? 答案是可以的,但只能是开多个进程来实现,那样弊端也显而易见,会增大资源开销而且进程间相互的切换也会非常复杂。
解决的着重点:协程+多进程/ IO多路复用

并发编程/GIL