并发编程/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多路复用 
时间: 2024-10-11 16:56:48

并发编程/GIL的相关文章

Python并发编程05/ 死锁/递归锁/信号量/GIL锁/进程池/线程池

目录 Python并发编程05/ 死锁/递归锁/信号量/GIL锁/进程池/线程池 1.昨日回顾 2.死锁现象与递归锁 2.1死锁现象 2.2递归锁 3.信号量 4.GIL全局解释器锁 4.1背景 4.2为什么加锁 5.GIL与Lock锁的区别 6.验证计算密集型IO密集型的效率 6.1 IO密集型 6.2 计算密集型 7.多线程实现socket通信 7.1服务端 7.2客户端 8.进程池,线程池 Python并发编程05/ 死锁/递归锁/信号量/GIL锁/进程池/线程池 1.昨日回顾 #生产者消

并发编程--一堆锁,GIL,同步异步,Event事件

目录 一堆锁 死锁现象(*****) 递归锁 RLock (了解) 信号量 (了解) GIL(*****) 什么时GIL锁 为什么需要GIL锁 Cpython解释器与GC的问题 GIL锁带来的问题 多线程与多进程性能对比 进程池与线程池 同步异步(*****) Event事件 一堆锁 死锁现象(*****) ? 死锁指的是,某个资源被占用之后,一直得不到释放,导致其他需要这个资源的线程进入阻塞状态 产生死锁的情况 对同一把互斥锁,进行了多次加锁 一个共享资源,在访问时必须具备多把锁,但是这些锁被

python-学习-python并发编程之多进程与多线程

一 multiprocessing模块介绍 python中的多线程无法利用多核优势,如果想要充分地使用多核CPU的资源(os.cpu_count()查看),在python中大部分情况需要使用多进程.Python提供了multiprocessing.    multiprocessing模块用来开启子进程,并在子进程中执行我们定制的任务(比如函数),该模块与多线程模块threading的编程接口类似.  multiprocessing模块的功能众多:支持子进程.通信和共享数据.执行不同形式的同步,

Python并发编程实例教程

有关Python中的并发编程实例,主要是对Threading模块的应用,文中自定义了一个Threading类库. 一.简介 我们将一个正在运行的程序称为进程.每个进程都有它自己的系统状态,包含内存状态.打开文件列表.追踪指令执行情况的程序指针以及一个保存局部变量的调用栈.通常情况下,一个进程依照一个单序列控制流顺序执行,这个控制流被称为该进程的主线程.在任何给定的时刻,一个程序只做一件事情. 一个程序可以通过Python库函数中的os或subprocess模块创建新进程(例如os.fork()或

并发编程之多线程

一.并发编程之多线程 1.线程简单介绍 进程是资源单位,把所有资源集中到一起,而线程是执行单位,真正执行的是线程 每个进程都有一个地址空间,而且默认就有一个控制线程 多线程:在一个进程中存在多个控制线程,多个控制线程共享该进程的地址空间.进程之间是竞争关系,线程之间是协作关系 线程的创建开销比进程小很多,运行较快 主线程从执行层面上代表了其所在进程的执行过程 2.线程开启方式 方式一:使用替换threading模块提供的Thread from threading import Thread  d

Python并发编程-线程

Python作为一种解释型语言,由于使用了全局解释锁(GIL)的原因,其代码不能同时在多核CPU上并发的运行.这也导致在Python中使用多线程编程并不能实现并发,我们得使用其他的方法在Python中实现并发编程. 一.全局解释锁(GIL) Python中不能通过使用多线程实现并发编程主要是因为全局解释锁的机制,所以首先解释一下全局解释锁的概念. 首先,我们知道C++和Java是编译型语言,而Python则是一种解释型语言.对于Python程序来说,它是直接被输入到解释器中直接运行的.解释器在程

Python中的并发编程

简介 我们将一个正在运行的程序称为进程.每个进程都有它自己的系统状态,包含内存状态.打开文件列表.追踪指令执行情况的程序指针以及一个保存局部变量的调用栈.通常情况下,一个进程依照一个单序列控制流顺序执行,这个控制流被称为该进程的主线程.在任何给定的时刻,一个程序只做一件事情. 一个程序可以通过Python库函数中的os或subprocess模块创建新进程(例如os.fork()或是subprocess.Popen()).然而,这些被称为子进程的进程却是独立运行的,它们有各自独立的系统状态以及主线

python并发编程&多线程(二)

前导理论知识见:python并发编程&多线程(一) 一 threading模块介绍 multiprocess模块的完全模仿了threading模块的接口,二者在使用层面,有很大的相似性 官网链接:https://docs.python.org/3/library/threading.html?highlight=threading#(装B模式加载中…………) 二 开启线程的两种方式  方式一  方式二 三 在一个进程下开启多个线程与在一个进程下开启多个子进程的区别  1 谁的开启速度快  2 瞅

9)网络并发 编程、进程、线程和协程

并发网络 Server: #!/usr/bin/env python#-*-conding:utf-8-*-import socketsk = socket.socket()sk.bind(('127.0.0.1',9009))sk.listen()conn,addr = sk.accept()conn.send(b'heooo')msg = conn.recv(1024)print(msg)conn.close()sk.close() Client: #!/usr/bin/env python