学习笔记(二十二)——了解进程和线程(代码片段)

别呀 别呀     2022-12-31     655

关键词:

一、进程

1.1、什么是程序

程序是指令和数据的有序集合,其本身没有任何运行的含义,是一个静态的概念。而进程则是在处理机上的一次执行过程,它是一个动态的概念。这个不难理解,其实进程是包含程序的,进程的执行离不开程序,进程中的文本区域就是代码区,也就是程序。


1.2、了解进程

进程就是一段程序的执行过程。它是一个具有一定独立功能的程序关于某个数据集合的一次运行活动。它是操作系统动态执行的基本单元,在传统的操作系统中,进程既是基本的分配单元,也是基本的执行单元。

简单的来讲进程的概念主要有两点:
进程是一个实体。每一个进程都有它自己的地址空间,一般情况下,包括文本区域(textregion)、数据区域(dataregion)和堆栈(stackregion)。文本区域存储处理器执行的代码;数据区域存储变量和进程执行期间使用的动态分配的内存;堆栈区域存储着活动过程调用的指令和本地变量。
进程是一个“执行中的程序”。程序是一个没有生命的实体,只有处理器赋予程序生命时,它才能成为一个活动的实体,我们称其为进程。


1.3、进程的三种状态

进程有三个状态,就绪、运行和阻塞。

  • 就绪态:其实就是获取了除cpu外的所有资源,只要处理器分配资源就可以马上执行。
  • 运行态:获得了处理器分配的资源,程序开始执行。
  • 阻塞态:当程序条件不够时候,需要等待条件满足时候才能执行,如等待i/o操作时候,此刻的状态就叫阻塞态。

1.4、多进程

Python中的多进程是通过multiprocessing包来实现的,和多线程的threading.Thread差不多,它可以利用multiprocessing.Process对象来创建一个进程对象。这个进程对象的方法和线程对象的方法差不多也有start(),run(), join()等方法,其中有一个方法不同Thread线程对象中的守护线程方法是setDeamon,而Process进程对象的守护进程是通过设置daemon属性来完成的。

Python多进程的实现方法,和多线程类似
实现示例:

from multiprocessing import  Process
def fun1(name):
    print('%s进程开启了' %name)

if __name__ == '__main__':
    for i in range(5):  #开启5个子进程执行fun1函数
        p = Process(target=fun1,args=(i,)) #实例化进程对象
        p.start()
        p.join()         #主进程阻塞

结果:

0进程开启了
1进程开启了
2进程开启了
3进程开启了
4进程开启了

join方法:是让主进程等待子进程运行完毕后再执行主进程的。(即主进程阻塞)
类的方式创建线程

from multiprocessing import  Process
class MyProcess(Process): #继承Process类
    def __init__(self,name):
        super(MyProcess,self).__init__()
        self.name = name

    def run(self):
        print(f'self.name进程开启了')

if __name__ == '__main__':
    for i in range(5):  #开启5个子进程执行fun1函数
        p = MyProcess(str(i)) #实例化进程对象
        p.start()
        p.join()

Process类的其他方法

构造方法:
Process([group [, target [, name [, args [, kwargs]]]]])
  group: 线程组 
  target: 要执行的方法
  name: 进程名
  args/kwargs: 要传入方法的参数

实例方法:
  is_alive():返回进程是否在运行,bool类型。
  join([timeout]):阻塞当前上下文环境的进程程,直到调用此方法的进程终止或到达指定的timeout(可选参数)。
  start():进程准备就绪,等待CPU调度
  run():strat()调用run方法,如果实例进程时未制定传入target,这star执行t默认run()方法。
  terminate():不管任务是否完成,立即停止工作进程

属性:
  daemon:和线程的setDeamon功能一样
  name:进程名字
  pid:进程号

二、线程

2.1、了解线程

通常在一个进程中可以包含若干个线程,当然一个进程中至少有一个线程,不然没有存在的意义。线程可以利用进程所拥有的资源,我们把进程作为分配资源的基本单位,而把线程作为独立运行和独立调度的基本单位


2.2、了解多线程

多线程是为了同步完成多项任务,不是为了提高运行效率,而是为了提高资源使用效率来提高系统的效率。线程是在同一时间需要完成多项任务的时候实现的。

多线程就像火车的每一节车厢,而进程则是火车。车厢离开火车是无法跑动的,同理火车也不可能只有一节车厢。多线程的出现就是为了提高效率。


2.3、进程与线程的区别

进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。

  1. 简而言之,一个程序至少有一个进程,一个进程至少有一个线程。
  2. 线程的划分尺度小于进程,使得多线程程序的并发性高。
  3. 另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
  4. 线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
  5. 从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区。

2.4、多线程实现

Python的标准库提供了两个模块:_threadthreading,_thread是低级模块,threading是高级模块,对_thread进行了封装。绝大多数情况下,我们只需要使用threading这个高级模块。启动一个线程就是把一个函数传入并创建Thread实例,然后调用start()开始执行。

补充知识点:主线程和子线程
程序执行时,程序本身就是一个线程,叫主线程。
手动创建的线程,叫子线程。
主线程的执行中不会等待子线程执行完毕,就会直接执行后面的代码创建线程。

实现示例

from threading import Thread
import time

def run(name):
    print(name,'线程执行了!')
    time.sleep(4)
#创建线程
t1 = Thread(target=run,args=('t1',))
t2 = Thread(target=run,args=('t2',))
#启动线程
t1.start()  
t2.start()

----结果:
t1 线程执行了!
t2 线程执行了!

类的方式创建线程

from threading import Thread
import time

class MyThread(Thread):
    def __init__(self,name):
        super(MyThread,self).__init__()
        self.name = name

    def run(self):
        print(self.name, '线程执行了!')
        time.sleep(4)

t1 = MyThread('t1')
t2 = MyThread('t2')
t1.start()
t2.start()

其他方法:

isAlive(): 返回线程是否活动的。
getName(): 返回线程名。
setName(): 设置线程名。
threading模块提供的一些方法:
threading.currentThread(): 返回当前的线程变量。
threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
threading.activeCount():返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。

2.5、线程锁

多线程可以同时运行多个任务但是当多个线程同时访问共享数据时,可能导致数据不同步,甚至错误!因此,就要使用线程锁。

线程锁:当有多个线程访问同一对象的加锁方法/代码块时,同一时间只有一个线程在执行,其余线程必须要等待当前线程执行完之后才能执行该代码段。但是,其余线程是可以访问该对象中的非加锁代码块的。

用法

#创建锁
lock = threading.Lock()
#锁定
lock.acquire([timeout])
#释放
lock.release()

优缺点

优点:保证资源同步
缺点:
等待肯定会慢

示例

import time
import threading

lock = threading.Lock()
num = 100
#出售
def sail(name):
    lock.acquire()   #上锁
    global num
    if num>0:
        num-=1
    print(name,'出售了一张电影票,还剩:',num,'张')
    lock.release()   #释放锁

#售票
while True:
    if num>0:
        A = threading.Thread(target=sail, args=('A售票员',))
        B = threading.Thread(target=sail, args=('B售票员',))
        A.start()
        B.start()
    else:
        break

2.6、全局解释锁(GIL)

不管系统CPU核心是多少,都保证python程序中同一时间点只能执行一个线程。它本本意上是为了实现数据安全问题,但从结果上却造成了cpu资源上的浪费,影响了程序执行的效率,因此弊大于利。(重点记)

我们可以通过使用多进程来解决GIL所造成的问题

学习笔记第二十二节课

shell介绍shell是一个命令解释器,提供用户和机器之间的交互。用户配置的最后一个段就是shell创建的普通的用户它的shell是binbash每个用户都可以有自己的shellsentos7的shell是bash除此之外还有zshksh,用起来和bash很像,但是有细节上... 查看详情

react学习案例二十二(代码片段)

React学习案例二十二MyComponent.propTypes=//可以声明prop为指定的JS基本数据类型,默认情况,这些数据是可选的optionalArray:React.PropTypes.array,optionalBool:React.PropTypes.bool,optionalFunc:React.PropTypes.func,optional 查看详情

objective-c学习笔记(二十二)——初始化方法init的重写与自己定义

     初学OC。对init这种方法不是非常了解。我们如今来分别对init方法进行重写以及自己定义,来加深对他的了解。本样例也是用Person类来进行測试。(一)重写init方法。(1)在Person.h中声明init方法:-(instancety... 查看详情

gui学习之二十二——qrubberband学习总结(代码片段)

今天学习一种全新的输入控件——QRubberBand()控件(橡皮筋选中)一.描述QRubberBand()提供了一个矩形或西安来只是选择或边界的效果(就像在桌面上点击鼠标后拖拽拉出来的框一样),一般和鼠标事件一同协作。该控件是继... 查看详情

javase学习笔记之io流(二十二)

IO流:用于处理设备上数据。流:可以理解数据的流动,就是一个数据流。IO流最终要以对象来体现,对象都存在IO包中。流也进行分类:1:输入流(读)和输出流(写)。2:因为处理的数据不同,分为字节流和字符流。 字... 查看详情

java基础二十二

1多线程的概述1.1进程就是正在运行的程序。是系统进行资源分配和调度的独立单位。每一个进程都有其自己的内存空间和系统资源。1.2多进程的意义?单进程的计算机只能做一件事情,而我们现在的计算机可以做多件事情。例... 查看详情

机器学习100天(二十二):022分类模型评价指标-python实现(代码片段)

机器学习100天!今天讲的是:分类模型评价指标-Python实现!《机器学习100天》完整目录:目录打开spyder,首先,导入标准库。importnumpyasnpimportmatplotlib.pyplotaspltfromsklearn.metricsimportaccuracy_scorefromsklearn.metricsimportprecision_scorefromsklear 查看详情

机器学习100天(二十二):022分类模型评价指标-python实现(代码片段)

机器学习100天!今天讲的是:分类模型评价指标-Python实现!《机器学习100天》完整目录:目录打开spyder,首先,导入标准库。importnumpyasnpimportmatplotlib.pyplotaspltfromsklearn.metricsimportaccuracy_scorefromsklearn.metricsimportprecision_scorefromsklear 查看详情

linuxc编程之二十二linux线程池实现(代码片段)

 一、线程池实现原理1.管理者线程(1)计算线程不够用创建线程(2)空闲线程太多   a.销毁更新要销毁的线程个数通过条件变量完成的   b.如果空闲太多,任务不够线程阻塞在该条件变量上  &nbs... 查看详情

小白学习c++教程二十二c++中的stl容器stackqueue和map(代码片段)

@Author:RunsenSTL中的栈容器是一种容器适配器。在栈容器中,元素在一端插入并在同一端删除。stack为了实现堆栈容器,我们需要在我们的程序中包含头文件<stack>。#include<stack>stack容器的一般声明语法是ÿ... 查看详情

c++笔记--linux编程(13)-守护进程-线程(代码片段)

目录进程组 概念和特性进程组操作函数(了解)会话创建会话getsid函数pid_tsetsid()会话和进程总结守护进程创建守护进程模型进程与线程线程标识线程调用线程创建pthread_create示例线程终止单个线程通过以下三种方式退出 线程退出... 查看详情

深度学习(二十二)dropout浅层理解与实现(代码片段)

...,了解一下其代码层面的实现。  Dropout是2012年深度学习视觉领域的开山之作paper:《ImageNet Classification with Deep Convolutional》所提到的算法,用于防止过拟合。在我刚入门深度学习,搞视觉的时候,就有所耳... 查看详情

swift学习笔记(二十二)——字典的基本操作

(1)计算字典长度。(2)推断字典是否为空。(3)查询字典元素。(4)取出字典元素进行拼接。(5)字典中插入一个键值对。(6)字典改动某个键值对。(7)用法更新元素值。事实上上述方法另一个返回值:(8)删除字典... 查看详情

爬虫学习笔记(二十一)——appium(代码片段)

一、概念和作用1.1、概念appium是一个移动App(手机应用)自动化工具。支持iOS平台和Android平台上的原生应用,web应用和混合应用。它允许测试人员在不同的平台(iOS,Android)使用同一套API来写自动化测试... 查看详情

wpf学习第二十二章文本控件(代码片段)

原文:【WPF学习】第二十二章文本控件  WPF提供了三个用于输入文本的控件:TextBox、RichTextBox和PasswordBox。PasswordBox控件直接继承自Control类。TextBox和RichTextBox控件间接继承自TextBoxBase类。  与前面看到的内容控件不同,文本框... 查看详情

python学习笔记(代码片段)

文章目录1.进程1.1.系统原生OS模块,创建进程1.2.multiprocessing模块1.2.1.Process单进程1.2.2.Pool进程池1.3.subprocess模块使用外部子进程2.线程2.1.threading模块,创建线程2.2.锁LOCK2.3.ThreadLocal模块,跨函数使用值1.进程线程是最小的执行单元,... 查看详情

python学习笔记-(十三)线程进程多线程&多进程(代码片段)

为了方便大家理解下面的知识,可以先看一篇文章:http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html线程1.什么是线程?线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线... 查看详情

python学习笔记-day-9(代码片段)

进程与线程什么是线程(thread)?线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行... 查看详情