深入了解进程与线程历史:从计算机组成、操作系统到进程的构成与执行

过程和线程的历史

深入了解进程与线程历史:从计算机组成、操作系统到进程的构成与执行

我们都知道计算机由硬件和软件组成。硬件中的CPU是计算机的核心,它执行计算机的所有任务。操作系统是在硬件上运行的软件。它是计算机管理器。它负责资源的管理和分配以及任务的调度。该程序是在系统上运行的软件,例如浏览器,音乐播放器等。每次执行程序时,都会完成某个功能。例如,浏览器可以帮助我们打开网页。为了确保其独立性,需要专门的管理和控制过程 - 过程控制块的数据结构。该过程是数据集上的动态执行过程。该过程通常由三个部分组成:程序,数据集和过程控制块。我们编写的过程用于描述什么功能以及如何完成过程;数据集是执行过程中程序所需的资源;它可用于控制和管理该过程,这是系统感知过程的唯一迹象。

在早期操作系统中,计算机只有一个核心,并且是过程执行程序的最小单位。任务调度采用了一种扣押的时间胶片旋转方法进行过程调度。每个过程都有自己的独立内存,以确保在过程之间隔离内存地址空间。随着计算机技术的发展,该过程有许多缺点。一个是,创建,撤销和切换过程的开销相对较大,另一个是由于对称的多重处理器(对称的多处理器(对称对称性处理器))在计算机上的一组处理器(Multi -cpus)的出现,一组处理器,共享内存子系统和CPU之间的总线结构的出现)可以符合多个操作单元,并且多过程并行支出太大。目前,引入了线程的概念。该线程也称为轻量级过程。它是基本的CPU执行单元,也是程序执行过程中最小的单元。它由线程ID,程序计数器,注册集和堆栈组成。线程的引入减少了程序并行执行的费用,并提高了操作系统的并发性能。该线程没有其自己的系统资源,只有在运行时才具有基本资源。但是,线程可以通过相同的过程和相同的过程共享其他资源。

过程与线程之间的关系

该线程属于该过程。线程在过程空间中运行。同一过程生成的线程共享相同的内存空间。当该过程退出时,该过程生成的线程将被强行退出和清除。该线程可以共享属于同一过程的共享过程的所有资源,但基本上没有系统资源本身。它只有一些在操作中必不可少的信息(例如程序计数器,一组寄存器和堆栈)。

Python线程

线程用于提供与线程相关的操作。该线程是应用程序中最小的单元。

1。线程模块

线程模块基于_thread模块。线程模块由低级别和原始方式处理和控制,并且线程模块通过第二个螺纹包装提供了更方便的API来处理线程。

import threading
import time
def worker(num):
 """
 thread worker function
 :return:
 """
 time.sleep(1)
 print("The num is %d" % num)
 return
for i in range(20):
 t = threading.Thread(target=worker,args=(i,),name=“t.%d” % i)
 t.start()

上面的代码创建了20个“前台”线程,然后将控制器移交给了CPU。 CPU是根据指定算法安排的,以执行指令。

线程方法描述

t.start():激活线程,

t.getName():获取线程的名称

t.setName():设置线程的名称

t.name:获取或设置线程的名称

t.is_alive():确定是否激活线程

t.isalive():确定是否激活线程

t.setDaemon()设置为背景线程或前台线程(默认:false);该线程是否由布尔值设置为监护线程,必须在执行start()方法之后使用它。如果是背景线程,则在主螺纹执行期间,也会执行背景线程。执行主线程后,无论是否成功,背景线程都将停止。执行主线程后,执行前台线程后,程序停止

t.isdaemon():确定它是否是守护线

T.INDER:获取线程的标识符。线程标识符是一个非零整数。仅在调用start()方法之后,它是有效的,否则只会返回无。

t.join():一个一个一个一个一个线执行,并在执行后继续执行。这种方法使多线程毫无意义

t.run():线程的运行方法由CPU安排后自动执行

2。螺纹锁定螺纹。rlock and threading.lock

由于线程是随机安排的,并且每个线程只能执行n执行,因此CPU遵循其他线程。为了确保数据的准确性,引入了锁定的概念。因此,可能发生以下问题:

示例:假设列表a的所有元素为0,当一个线程从正面到后面打印列表的所有元素时,另一个线程将列表从背面到0的列表修改,部分为1 ,这导致数据不一致。锁的出现解决了这个问题。

import threading
import time
globals_num = 0
lock = threading.RLock()
def Func():
 lock.acquire() # 获得锁 
 global globals_num
 globals_num += 1
 time.sleep(1)
 print(globals_num)
 lock.release() # 释放锁 
for i in range(10):
 t = threading.Thread(target=Func)
 t.start()

3。

Rlock允许许多人在同一线程中获取。锁定不允许这种情况。如果您使用rlock,那么获取和释放必须成对出现,也就是说,呼叫称为n次,并且必须调用n次的释放才能真正释放琐事。

import threading
lock = threading.Lock() #Lock对象
lock.acquire()
lock.acquire() #产生了死琐。
lock.release()
lock.release()  
import threading
rLock = threading.RLock() #RLock对象
rLock.acquire()
rLock.acquire() #在同一线程内,程序不会堵塞。
rLock.release()
rLock.release()

4。线程

Python线程的事件用于主线程执行其他线程。该事件主要提供三种设置,等待和清除的方法。

事件处理机制:全局定义了“标志”。如果“标志”值为false,则当程序执行事件时,将被阻止。然后阻止。

•清除:将“标志”设置为false

•设置:将“标志”设置为true

• event.isset():确定标识符是否为ture。

import threading
def do(event):
  print('start')
  event.wait()
  print('execute')
event_obj = threading.Event()
for i in range(10):
  t = threading.Thread(target=do, args=(event_obj,))
  t.start()
event_obj.clear()
inp = input('input:')
if inp == 'true':
  event_obj.set(

执行线程时,如果标志为false,则线程将阻止。当标志为真时,线程将不会被阻止。它提供本地和远程并发。

5。螺纹。条件

条件变量始终与某些类型的锁相连。默认情况下可以使用或创建一个。当必须使用相同锁定的几个条件变量时,它非常有用。锁定是Conditon对象的一部分:无需单独跟踪。

条件变量在关闭单词块之前遵守与锁的连接。 Acceare()和Release()调用与锁定相关的相应方法。

必须调用与锁相关的其他方法。 Wait()方法释放锁。当另一个线程使用Notify()或Notify_all()将其唤醒时,它将始终被阻止。醒来后,wait()将被锁定并返回,

条件类实现科尔顿变量。此conditiaon变量允许一个或多个线程,直到另一个线程通知它们为止。如果给出了锁定参数一个非空值,则他必须是锁定对象,用于制作基础锁定。否则,将为下面的锁创建一个新的Rlock对象。

•等待(超时=无):等待通知,或等到设置超时。当调用此Wait()方法时,如果线程调用未锁定,它将抛出RuntimeError异常。在WATI()释放锁之后,在使用相同的过程中醒来之前,将阻止称为或Notify_all()的另一个过程。 wait()也可以指定超时。

如果有等待线程,则Notify()方法唤醒了等待Conditon变量的线程。 notify_all()唤醒所有等待conditon变量的线程。

注意:notify()和notify_all()不会释放锁,也就是说,线程不会在唤醒后立即返回其wait()呼叫。除非线程呼叫notify()和notify_all(),否则锁所有权被放弃。

在典型的设计样式中,使用条件变量使用锁来访问某些共享状态。在您想要的状态之前,该线程将反复调用Wait()。修改状态调用notify()或Notify_all()更改状态时。这样,线程将尽可能获得所需的服务员状态。示例:生产者消费者模型,

import threading
import time
def consumer(cond):
  with cond:
    print("consumer before wait")
    cond.wait()
    print("consumer after wait")
def producer(cond):
  with cond:
    print("producer before notifyAll")
    cond.notifyAll()
    print("producer after notifyAll")
cOndition= threading.Condition()
c1 = threading.Thread(name="c1", target=consumer, args=(condition,))
c2 = threading.Thread(name="c2", target=consumer, args=(condition,))
p = threading.Thread(name="p", target=producer, args=(condition,))
c1.start()
time.sleep(2)
c2.start()
time.sleep(2)
p.start()

6。队列模块

队列是队列,是线程安全性

例如,我们去麦当劳吃晚饭。餐厅里有一个厨师职位。前台负责将厨房出售给客户,客户去前台接受美食。这里的前台等同于我们的队列。厨师组成了一条管道,通过前台将其很好地交付给客户。 SO称为一个-way队列

该模型也称为生产者消费者模型。

导入队列

q = queue.queue(maxsize = 0)#构造高级显示队列。 MaxSize指定队列长度。当0时,这意味着队列长度是无限的。

Q.Join()#等到队列为Kong,执行其他操作

qsize()#返回队列的大小(不可靠)

q..empty()#当队列为空时,返回true,否则返回false(不可靠)

q.full()#当队列已满时,返回到true,否则返回false(不可靠)

Q.put(item,block = true,timeout = none)#将项目放入队列的尾部。项目必须存在,并且参数块默认为默认值。这意味着,当队列已满时,它将等待队列提供可用位置。

当它是错误的时,这是一个非块。目前,如果队列已满,它将导致队列。可选的参数超时,表明设置的时间将被阻止。

如果队列无法在项目中给出位置,则会导致队列。

q.get(block = true,timeout = none)#删除并返回队列头的值。可选的参数块默认为true,表明当采集值为空时,当队列为空时,当被阻止时,则为false。不要阻止,

如果队列目前为空,则会导致Qineue.Empty异常。可选参数超时,表明它将阻止设计

放置时,队列为空后会导致空异常。

Q.put_nowait(item)#等价(item,block = false)

q.get_nowait()#get中的等效物(item,block = false)

代码如下:

#!/usr/bin/env python
import Queue
import threading
message = Queue.Queue(10)
def producer(i):
  while True:
    message.put(i)
def consumer(i):
  while True:
    msg = message.get()
for i in range(12):
  t = threading.Thread(target=producer, args=(i,))
  t.start()
for i in range(10):
  t = threading.Thread(target=consumer, args=(i,))
  t.start()

然后自己做一个线程池:

方法一

# 简单往队列中传输线程数
import threading
import time
import queue
class Threadingpool():
  def __init__(self,max_num = 10):
    self.queue = queue.Queue(max_num)
    for i in range(max_num):
      self.queue.put(threading.Thread)
  def getthreading(self):
    return self.queue.get()
  def addthreading(self):
    self.queue.put(threading.Thread)
def func(p,i):
  time.sleep(1)
  print(i)
  p.addthreading()
if __name__ == "__main__":
  p = Threadingpool()
  for i in range(20):
    thread = p.getthreading()
    t = thread(target = func, args = (p,i))
    t.start()

方法两个

#往队列中无限添加任务
import queue
import threading
import contextlib
import time
StopEvent = object()
class ThreadPool(object):
  def __init__(self, max_num):
    self.q = queue.Queue()
    self.max_num = max_num
    self.terminal = False
    self.generate_list = []
    self.free_list = []
  def run(self, func, args, callback=None):
    """
    线程池执行一个任务
    :param func: 任务函数
    :param args: 任务函数所需参数
    :param callback: 任务执行失败或成功后执行的回调函数,回调函数有两个参数1、任务函数执行状态;2、任务函数返回值(默认为None,即:不执行回调函数)
    :return: 如果线程池已经终止,则返回True否则None
    """
    if len(self.free_list) == 0 and len(self.generate_list) 

Python过程

多处理是Python的多进程管理软件包,类似于螺纹。

1。多处理模块

直接使用子过程从侧面替换线程。因此,多处理模块允许程序员在给定的计算机上充分使用CPU。在多处理中,通过创建创建过程的过程来生成过程,然后调用其start()方法,

from multiprocessing import Process
def func(name):
  print('hello', name)
if __name__ == "__main__":
  p = Process(target=func,args=('zhangyanlin',))
  p.start()
  p.join() # 等待进程执行完毕

最好在使用并发设计时避免尽可能多地共享数据,尤其是在使用多个过程时。如果您确实需要共享数据,那么多处理提供了两种方法。

(1)多处理,数组,值

数据可以存储在带有值或数组的共享内存映射中,如下所示:

from multiprocessing import Array,Value,Process
def func(a,b):
  a.value = 3.333333333333333
  for i in range(len(b)):
    b[i] = -b[i]
if __name__ == "__main__":
  num = Value('d',0.0)
  arr = Array('i',range(11))
  c = Process(target=func,args=(num,arr))
  d= Process(target=func,args=(num,arr))
  c.start()
  d.start()
  c.join()
  d.join()
  print(num.value)
  for i in arr:
    print(i)
输出:
  3.1415927
  [0, -1, -2, -3, -4, -5, -6, -7, -8, -9]

创建NUM和ARR时,“ D”和“ I”参数是由数组模块使用的TypeCodes创建的:“ D”代表双重精确的浮点数,“ I”代表符号整数。这些共享对象将是安全线程安全处理。

数组('i',range(10))中的“ i”参数:

'c':ctypes.c_char'u':ctypes.c_wchar'b':ctypes.c_byte'b':ctypes.c_ubyte

'h':ctypes.c_short'h':ctypes.c_ushort'i是:ctypes.c_int':ctypes.c_uint

'l':ctypes.c_long,'l':ctypes.c_ulong'f':ctypes.c_float'd':ctypes.c_double

(2)多处理,经理

Manager()由Manager()提供的列表,词典,命名空间,锁,岩石,信号量,边界eMaphore,conition,conition,event,barrier,queue,value和array。

from multiprocessing import Process,Manager
def f(d,l):
  d["name"] = "zhangyanlin"
  d["age"] = 18
  d["Job"] = "pythoner"
  l.reverse()
if __name__ == "__main__":
  with Manager() as man:
    d = man.dict()
    l = man.list(range(10))
    p = Process(target=f,args=(d,l))
    p.start()
    p.join()
    print(d)
    print(l)

输出:   {0.25: None, 1: '1', '2': 2}   [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

服务器过程管理器比共享内存更灵活,因为它可以支持任意对象类型。此外,可以通过该过程在网络上的不同计算机之间共享一个单独的管理器,但是他比共享内存慢。

2。过程池

池类类描述了一个工作过程池,他有几种不同的方法来卸载任务以卸载工作过程。

过程池内部保持过程序列。使用时,请转到过程池获取过程。如果过程池序列中没有可用的过程,则该程序将等到进程池中的可用过程。

我们可以使用池类类创建一个进程池,并启动提交到过程池的任务。例子:

#apply
from multiprocessing import Pool
import time
def f1(i):
  time.sleep(0.5)
  print(i)
  return i + 100
if __name__ == "__main__":
  pool = Pool(5)
  for i in range(1,31):
    pool.apply(func=f1,args=(i,))
#apply_async
def f1(i):
  time.sleep(0.5)
  print(i)
  return i + 100
def f2(arg):
  print(arg)
if __name__ == "__main__":
  pool = Pool(5)
  for i in range(1,31):
    pool.apply_async(func=f1,args=(i,),callback=f2)
  pool.close()
  pool.join()

过程池对象可以控制可以提交过程池的哪些工作。它支持加班和回调的异步结果,并且有一个类似地图的实现。

•进程:使用的工作过程数量,如果过程没有,则由OS.CPU_COUNT()返回的数字。

• initializer:如果初始化器无,则每个工作过程都会调用initializer(*oittargs)。

• Maxtasksperchild:在退出工作过程之前可以完成的任务数量。完成后,使用心理工作过程替换原始过程以发布空闲资源。默认情况下,Maxtasksperchild并非不是,这意味着只要池中存在于工作过程中,它将始终生存。

•上下文:用于制定工作过程的上下文。通常,多处理。pool()或上下文对象的池()方法来创建池。两种方法都适当地设置为上下文

注意:池对象的方法只能通过创建池的过程来调用。

验证3.2:maxasksperchild

Vering 3.4:上下文中的新事物

过程池法

应用(func [,args [,kwds]]):使用arg和kwds参数调用func函数。结果,它将始终在返回之前被阻止。 apply_async()更适合执行。另外,FUNC功能仅在池中。一个过程运行。

apply_async(func [,args [,kwds [,callback [,error_callback]]]]]]]:apply()方法的变体返回结果对象。如果指定了回调,则回调可以接收参数,然后呼叫。当结果准备好调用回调时,将调用回调。当呼叫失败时,将使用error_callback来替换回调。回调应立即完成,否则处理结果的线程将被阻止。

关闭():防止更多任务提交给池。任务完成后,工作过程将退出。

终止():无论任务是否完成,都可以立即停止工作过程。回收池对象过程的过程时,将立即调用terminate()。

join():等待工作线程的退出,在调用join()之前,您必须调用colles()或terminate()。这是因为终止过程需要由父进程调用。

map(func, iterable[, chunksize])¶
map_async(func, iterable[, chunksize[, callback[, error_callback]]])¶
imap(func, iterable[, chunksize])¶
imap_unordered(func, iterable[, chunksize])
starmap(func, iterable[, chunksize])¶
starmap_async(func, iterable[, chunksize[, callback[, error_back]]])

Coroutine

程序的操作和过程是由程序触发的,以触发系统接口,最终的执行程序是系统。 Coroutine的操作是程序员。

校正的意义:对于多线程应用程序,CPU用于在片段执行线之间切换。时间消耗是时间 - 耗费(存储状态,下次继续)。 Coroutine仅使用一个线程,该线程规定了一个线程中代码块的序列。

适用的校正方案:当有大量操作(IO)不需要程序中的CPU时,它适用于Coroutine;

事件循环是Coroutine执行的控制点。如果要执行Coroutine,则需要使用它们。

事件循环提供以下功能:

•注册,执行,取消延迟电话(异步函数)

•创建客户和服务器协议(工具)以进行通信

•创建子过程和协议(工具)以与其他过程创建和通信

•将功能发送到线程池

例子:

import asyncio
async def cor1():
  print("COR1 start")
  await cor2()
  print("COR1 end")
async def cor2():
  print("COR2")
loop = asyncio.get_event_loop()
loop.run_until_complete(cor1())
loop.close()

最后三行是重点。

• asyncio.get_event_loop():asyncio启动默认事件循环

• RUN_UNTIL_COMPLETE():知道所有异步函数都完成,该功能已妨碍

•关闭():关闭事件循环。

1。格林

import greenlet
def fun1():
  print("12")
  gr2.switch()
  print("56")
  gr2.switch()
def fun2():
  print("34")
  gr1.switch()
  print("78")
gr1 = greenlet.greenlet(fun1)
gr2 = greenlet.greenlet(fun2)
gr1.switch()

2。GEVENT

Gevent属于下载和安装软件包的第三方模块

pip3 install --upgrade pip3
pip3 install gevent
import gevent
def fun1():
  print("www.baidu.com")  # 第一步
  gevent.sleep(0)
  print("end the baidu.com") # 第三步
def fun2():
  print("www.zhihu.com")  # 第二步
  gevent.sleep(0)
  print("end th zhihu.com") # 第四步
gevent.joinall([
  gevent.spawn(fun1),
  gevent.spawn(fun2),
])

遇到IO操作时自动切换:

import gevent
import requests
def func(url):
  print("get: %s"%url)
  gevent.sleep(0)
  date =requests.get(url)
  ret = date.text
  print(url,len(ret))
gevent.joinall([
  gevent.spawn(func, 'https://www.python.org/'),
  gevent.spawn(func, 'https://www.yahoo.com/'),
  gevent.spawn(func, 'https://github.com/'),
])

以上是对小小比介绍的多过程,多线程和与Coroutine相关的知识的深入分析。我希望这对每个人都会有所帮助。如果您有任何疑问,请给我留言。每个人。非常感谢您对网站的支持!

你可能想看:
« 上一篇
下一篇 »

相关推荐

python爬虫教程PDF,Python爬虫书PDF

2026年09月02日

31阅读

外国教程python,python编程教学视频

2026年09月02日

25阅读

python简明教程沈洁元,python详细基础教程

2026年09月02日

21阅读

python库包教程,python 包

2026年09月02日

27阅读

python教程大全集,python教程600集

2026年09月02日

26阅读

python入门教程完整版,python零基础入门全套教程视频

2026年09月02日

22阅读