您的位置:首页 > 房产 > 建筑 > 收图片的网站_世界疫情最新数据排名表2022年_怎么免费建个人网站_优秀品牌策划方案

收图片的网站_世界疫情最新数据排名表2022年_怎么免费建个人网站_优秀品牌策划方案

2025/4/22 2:28:34 来源:https://blog.csdn.net/m0_61388098/article/details/147227717  浏览:    关键词:收图片的网站_世界疫情最新数据排名表2022年_怎么免费建个人网站_优秀品牌策划方案
收图片的网站_世界疫情最新数据排名表2022年_怎么免费建个人网站_优秀品牌策划方案

一、进程和线程简介

1.概念
1.1多任务

程序的运行是CPU和内存协同工作的结果

操作系统比如Mac OS X,UNIX,Linux,Windows等,都是支持“多任务”的操作系统

问题1:什么是多任务?

​ 就是操作系统可以同时运行多个任务。打个比方,你一边在用浏览器上网,一边在听MP3,一边在用Word赶作业,这就是多任务,至少同时有3个任务正在运行。还有很多任务悄悄地在后台同时运行着,只是桌面上没有显示而已

问题2:多核CPU已经非常普及了,但是,即使过去的单核CPU,也可以执行多任务。由于CPU执行代码都是顺序执行的,那么,单核CPU是怎么执行多任务的呢?

​ 答案:操作系统轮流让各个任务交替执行,任务1执行0.01秒,切换到任务2,任务2执行0.01秒,再切换到任务3,执行0.01秒……这样反复执行下去。实际上,每个任务都是交替执行的,但是,表面上看,由于CPU的执行速度实在是太快了,我们感觉就像所有任务都在同时执行一样【现在的电脑最起码都4核起】

并行:真正一起执行,任务数量小于cpu的核心数量【理想型】

并发:看上去一起执行,任务数量大于cpu的核心数量【现实型】

​ 多核cpu实现多任务的原理:真正的并行执行多任务只能在多核cpu上实现,但是由于任务数量远远远多于cpu的核心数量,所以操作系统也会自动把很多任务轮流调度到每个核心上执行

​ 对于操作系统而言,一个任务就是一个进程【process】,一个操作系统可以开启多个进程;有的进程启动之后,有可能又需要处理多个子任务,这些子若任务被称为线程【thread】

1.2进程

是一个程序的运行状态和资源占用(内存,CPU)的描述

进程是程序的一个动态过程,它指的是从代码加载到执行完毕的一个完整过程

【面试题】进程的特点:

​ a.独立性:不同的进程之间是独立的,相互之间资源不共享(举例:两个正在上课的教室有各自的财产,相互之间不共享)

​ b.动态性:进程在系统中不是静止不动的,而是在系统中一直活动的(举例:教室里一直在讲课)

​ c.并发性:多个进程可以在单个处理器上同时进行,且互不影响(举例:一栋教学楼是处理器,多个教室同时上课就相当于多个进程,相互之间不影响)

1.3线程

​ 线程是进程的组成部分,一个进程可以有多个线程,每个线程去处理一个特定的子任务

​ 线程的执行是抢占式的,多个线程在同一个进程中可以并发执行,其实就是CPU快速的在不同的线程之间切换,也就是说,当前运行的线程在任何时候都有可能被挂起,以便另外一个线程可以运行

​ 多线程:

​ 在一个进程中,多个线程可以同时进行

​ 多线程是实现了并发机制的一种有效手段,一个进程中可以包含多个线程,不同线程之间是可以资源共享的,同时运行可以提高程序的执行效率,可以同时完成多个工作

【面试题】简述进程和线程之间的区别和联系

​ a.一个程序启动之后,肯定会启动一个进程

​ b.一个进程启动之后,可能会启动多个线程,但是,该进程至少需要一个线程,否则进程是没有意义的

​ c.多个进程之间资源不共享,多个线程之间资源共享

​ d.系统创建进程需要为进程重新分配系统资源,而创建线程则容易的多,所以在实际开发中,使用多线程多于多进程

二、进程

1.单任务现象
def func():while True:print('222222')
​
if __name__ == '__main__':# 任务一while True:print('111111')
​# 任务二func()
​'''在上述代码中,任务二必须等待任务一执行完毕,才有执行的机会多个任务必须按照顺序执行,当一个任务执行时,其他任务必须处于等待状态,这种现象被称为单任务现象'''
2.多进程实现多任务
2.1启动进程实现多任务

Unix/Linux操作系统提供了一个fork()系统调用,fork()存在于os模块下【os.fork()】,但是,Windows没有fork调用

由于Python是跨平台的,提供了一个跨平台的多进程支持。multiprocessing模块就是跨平台版本的多进程模块

multiprocessing模块提供了一个Process类来代表一个进程对象

# 1.导入模块
from multiprocessing import  Process
import os,time
​
# 子进程需要处理的任务
def func():print(f'子进程启动,进程号:{os.getpid()},对应的父进程:{os.getppid()}')while True:print('222222')time.sleep(0.5)
​
def func1(a,b,c):print(a,b,c,a + b + c)print(f'子进程启动,进程号:{os.getpid()},对应的父进程:{os.getppid()}')while True:print('222222')time.sleep(0.5)
​
if __name__ == '__main__':# 2.# 只要运行程序,则默认表示启动了一个进程,该进程被称为主进程/父进程# 注意:系统会自动给启动的进程分配一个进程号,通过od.getpid可以获取print(f'父进程启动,进程号:{os.getpid()}')
​# 3.在父进程中创建一个子进程# 注意:进程对象创建之后,一定要手动启动'''Process(target,args)target:当前进程需要执行的任务的函数名args:表示任务函数的参数。值一定是一个元组'''# a.任务函数没有参数# p = Process(target=func)# p.start()
​# b.任务函数有参数p = Process(target=func1,args=(34,6,7))p.start()
​# 父进程需要处理的任务while True:print('111111')time.sleep(1)
2.2合并进程
from multiprocessing import  Process
import  os,time
​
def task():print(f'子进程启动,进程号:{os.getpid()}')print(3536523)time.sleep(5)print(f'子进程结束~~~~,进程号:{os.getpid()}')
​
if __name__ == '__main__':print(f'父进程启动,进程号:{os.getpid()}')
​# 创建子进程p = Process(target=task)p.start()
​'''默认情况下,根据系统的调度,主进程可能会早于子进程结束但是将子进程进行合并【join】之后,主进程等待子进程执行完毕之后才结束,子进程相当于做了插队操作'''# join一定要在start之后,否则报错:AssertionError: can only join a started processp.join()
​print('main~~~~~')time.sleep(1)
​print(f'父进程结束~~~~~,进程号:{os.getpid()}')
'''
join之前
父进程启动,进程号:7792
main~~~~~
子进程启动,进程号:13904
3536523
父进程结束~~~~~,进程号:7792
子进程结束~~~~,进程号:13904
​
join之后
父进程启动,进程号:3772
子进程启动,进程号:12468
3536523
子进程结束~~~~,进程号:12468
main~~~~~
父进程结束~~~~~,进程号:3772
'''
2.3多个进程中的全局变量
from multiprocessing import  Process
import  os,time
​
# 需求:在子进程中修改全局变量,查看父进程中访问到的全局变量的值
num  = 100
​
def task():print('子进程启动~~~~')global numnum += 50time.sleep(2)print('子进程结束~~~~~')print(f'子进程,全局变量num={num}~~~~~')  # 150
​
if __name__ == '__main__':print('父进程启动')
​p = Process(target=task)p.start()
​# 合并进程p.join()
​print('主进程的任务执行了****')
​print('父进程结束')print(f'父进程,全局变量num={num}')   # 100
​'''总结:验证了进程之间是独立的,相互之间资源不共享工作原理:在创建子进程对象的时候,会将所有的全局变量数据进行备份每个进程都有自己的代码段,数据段和堆栈段,所以进程之间是独立的,资源不共享'''

三、线程

多任务可以由多进程完成,也可以由一个进程内的多线程完成

在一个进程的内部,要同时干多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”叫做线程

线程通常叫做轻型的进程。线程是共享内存空间的并发执行的多任务,每一个线程都共享一个进程中的资源

线程是最小的执行单元,而进程由至少一个线程组成。如何调度进程和线程,完全由操作系统决定,程序自己不能决定什么时候执行,也不能决定执行多长时间

而且线程是操作系统直接支持的执行单元,因此,高级语言通常都内置多线程的支持,Python也不例外,并且,Python的线程是真正的Posix Thread,而不是模拟出来的线程

模块

1、_thread模块:提供了低级别的、原始的线程【低级并不是不好,只是功能比较有限,底层采用的是c语言封装的】
​
2、threading模块:高级模块,对_thre
ad进行了封装,并提供了_thread中没有的功能
​
绝大多数情况下,我们只需要使用threading这个高级模块
1.创建线程

创建并启动一个线程就是把一个函数传入并创建Thread实例,然后调用start()开始执行

# 1.导入模块
from  threading import *
import  os,time
​
def task1():print(f'子线程启动~~~~~~:{current_thread().name}')time.sleep(5)print(f'子线程结束~~~~~~:{current_thread().name}')
​
def task2(a,b):print(f'子线程启动~~~~~~:{current_thread().name}')print(a,b)time.sleep(5)print(f'子线程结束~~~~~~:{current_thread().name}')
​
if __name__ == '__main__':# 2.任何一个程序启动之后,会启动一个进程,该进程被称为父进程,同时,该进程会默认启动一个线程,该线程被称为主线程# current_thread().name获取的是当前正在执行的线程的名称,主线程的默认名称为MainThreadprint(f'主进程{os.getpid()}中的主线程启动:{current_thread().name}')
​# 3.创建子线程'''Thread(target,args,name)target:当前线程需要执行的任务的函数名args:表示任务函数的参数。值一定是一个元组name:给线程命名'''# 注意:子线程默认的名称为Thread-1,Thread-2.....# a.任务函数无参# t = Thread(target=task1)# t.start()
​# t = Thread(target=task1,name='hello')# t.start()
​# b.任务函数有参t = Thread(target=task2,args=(34,19),name='abc')t.start()
​# 和进程的用法类似,也可以合并线程,则该线程优先执行t.join()
​time.sleep(1)
​print(f'主进程{os.getpid()}中的主线程结束:{current_thread().name}')
​
2.线程中的全局变量
from threading import  Thread
​
num = 0
​
def change(n):global  numnum += nnum -= n      # 0
​
def task(m):for _ in range(10000000):# 共享资源change(m)
​
if __name__ == '__main__':print('主线程启动~~~~')t1 = Thread(target=task,args=(5,))t2 = Thread(target=task, args=(8,))t1.start()t2.start()
​t1.join()t2.join()
​print('主线程结束~~~~~')print(f'全局变量num={num}')
​'''原因:多个线程之间资源是共享的,所以当多个线程同时访问一个全局变量的时候,会导致全局变量的结果和理论不一致分析:num += n-----》第一步:x = num + n   第二步:num = xt1:x1 = num + n       x1 = 5t2:x2 = num + n       x2 = 8t2:num = x2          num = 8t1:num = x1         num = 5t1:x1 = num - n     x1 = 0t1:num = x1         num = 0t2:x2 = num - n    x2 = -8t2:num = x2         num = -8解决:只需要保证一个线程抢到时间片之后,能够将所有的代码执行完毕,其他线程处于等待状态实现:给共享资源加锁,哪个线程抢到时间片,则该线程持有锁,当共享资源对应的代码执行完毕,则释放锁'''
3.线程锁
from threading import  *
​
# 创建一个锁对象
lock = Lock()
​
num = 0
​
def change(n):global  numnum += nnum -= n      # 0
​
def task(m):for _ in range(10000000):# 获取锁lock.acquire()try:# 共享资源change(m)finally:# 释放锁lock.release()
​
if __name__ == '__main__':print('主线程启动~~~~')t1 = Thread(target=task,args=(5,))t2 = Thread(target=task, args=(8,))t1.start()t2.start()
​t1.join()t2.join()
​print('主线程结束~~~~~')print(f'全局变量num={num}')
from threading import  *
​
# 创建一个锁对象
lock = Lock()
​
num = 0
​
def change(n):global  numnum += nnum -= n      # 0
​
def task(m):for _ in range(10000000):# 进入with代码块,则表示获取锁,当with代码块执行完毕,会自动释放锁with lock:# 共享资源change(m)
​
if __name__ == '__main__':print('主线程启动~~~~')t1 = Thread(target=task,args=(5,))t2 = Thread(target=task, args=(8,))t1.start()t2.start()
​t1.join()t2.join()
​print('主线程结束~~~~~')print(f'全局变量num={num}')

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com