代理龙华网站建设,前沿的设计网站,微信公众号开发需要什么技术,百度的营销策略后续很快就要进入Spark的学习#xff0c;在学习之前也是要铺垫一个知识点#xff1a;进程是什么#xff1f;线程是什么#xff1f;两者有什么区别#xff1f;又有什么关系#xff1f;
一. 并发与并行
并发#xff1a;在一段时间内快速交替去执行多个任务#xff08;多…后续很快就要进入Spark的学习在学习之前也是要铺垫一个知识点进程是什么线程是什么两者有什么区别又有什么关系
一. 并发与并行
并发在一段时间内快速交替去执行多个任务多线程并行在一段时间内真正的同时一起执行多个任务多进程
二. 进程(Process)
是操作系统进行资源分配的基本单位进程可以有一个或多个子进程最原始的父进程是由操作系统提供的进程之间不共享变量子进程可以设置为守护进程主进程主动终止子进程
多线程示例
import time
import os
import multiprocessing
# os.getpid()process id获取进程的编号
# os.getppid()parent process id获取父进程编号# 跳舞函数
def dance():print(fdance进程的编号{os.getpid()}父进程编号{os.getppid()})for i in range(5):print(跳舞中...)# 休眠1秒钟time.sleep(1)# 唱歌函数
def sing():print(fsing进程的编号{os.getpid()}父进程编号{os.getppid()})for i in range(5):print(唱歌中...)# 休眠1秒钟time.sleep(1)if __name__ __main__:# 最原始的父进程是由操作系统提供的print(f主进程的编号为{os.getpid()}父进程编号{os.getppid()})# 创建两个进程一个执行 dance 函数另一个执行 sing 函数dance_process multiprocessing.Process(targetdance)sing_process multiprocessing.Process(targetsing)# 启动进程dance_process.start()sing_process.start()多线程执行带有参数的任务示例
import multiprocessing
import time# 带有参数的任务(函数)
def task(count):for i in range(count):print(任务执行中...)time.sleep(0.2)else:print(任务执行完成)if __name__ __main__:# 传参方式1 args(参数值1, ...)# task_process multiprocessing.Process(targettask, args(3,))# 传参方式2 kwargs{形参字符串1: 值1, 形参字符串2: 值2, ...}task_process multiprocessing.Process(targettask, kwargs{count: 5})# 启动进程task_process.start()task_process.join()print(这行代码一定等task_process进程执行完毕之后才会运行打印)进程之间不共享变量示例
import multiprocessing
import time# 定义全局变量
g_list []# 添加数据的函数
def add_data():for i in range(5):g_list.append(i)print(add, i)time.sleep(0.2)print(add, g_list)# 读取数据的函数
def read_data():print(read, g_list)if __name__ __main__:# 创建添加数据的子进程add_data_process multiprocessing.Process(targetadd_data)# 创建读取数据的子进程read_data_process multiprocessing.Process(targetread_data)# 启动添加数据子进程add_data_process.start()# 阻塞等待主进程等待 add_data_process 执行完成再向下继续执行add_data_process.join()# 启动读取数据子进程read_data_process.start()# 主进程读取数据print(main, g_list)# 主进程延时 1stime.sleep(1)print(主进程结束)子进程设为守护进程示例
主进程结束设为守护进程的子进程主动结束
import multiprocessing
import timedef task():for i in range(10):print(任务执行中...)time.sleep(0.5)if __name__ __main__:# 创建子进程并启动sub_process multiprocessing.Process(targettask)# TODO设置子进程为守护进程sub_process.daemon Truesub_process.start()# 主进程延时 1stime.sleep(1)print(主进程结束)主进程终止子进程
子进程被动结束
import multiprocessing
import time# 任务函数
def task():for i in range(10):print(任务执行中...)time.sleep(0.5)if __name__ __main__:# 创建子进程并启动sub_process multiprocessing.Process(targettask)sub_process.start()# 主进程延时 1stime.sleep(1)print(主进程结束)# TODO: 终止子进程sub_process.terminate()
三. 线程(Thread)
是CPU进行调度的基本单位线程可以有一个或多个子线程线程是由进程主动创建出来的创建第一次创建子线程时才会出现主线程线程共用全局变量
多线程示例
import time
import threading# 跳舞函数
def dance(num):for i in range(num):print(跳舞中...)time.sleep(1)# 唱歌函数
def sing(num):for i in range(num):print(唱歌中...)time.sleep(1)if __name__ __main__:# 创建两个线程分别执行 dance 和 singdance_thread threading.Thread(targetdance, args(5,))sing_thread threading.Thread(targetsing, kwargs{num:5})# 启动线程dance_thread.start()sing_thread.start()线程公用全局变量示例
import threading
import time# 定义全局变量
g_list []# 添加数据的函数
def add_data():for i in range(5):g_list.append(i)print(add, i)time.sleep(0.2)print(add, g_list)# 读取数据的函数
def read_data():print(read, g_list)if __name__ __main__:# 创建添加数据的子线程add_data_thread threading.Thread(targetadd_data)# 创建读取数据的子线程read_data_thread threading.Thread(targetread_data)# 启动添加数据子线程add_data_thread.start()# 阻塞等待主线程等待 add_data_thread 执行完成再向下继续执行add_data_thread.join()# 启动读取数据子线程read_data_thread.start()# 阻塞等待主线程等待 read_data_thread 执行完成再向下继续执行read_data_thread.join()print(main, g_list)join()使用总结 1- 作用线程等待子线程执行结束 2- 使用场景主线程需要使用多个子线程运行的最终结果才能够继续往下运行。
线程互斥锁示例 注释lock锁相关代码并使用 低版本的Python解释器python3.6.5 才能看到线程资源安全问题的效果Python 3.10 已经解决了该问题 # 互斥锁多个线程去抢同一把锁抢到锁的线程执行没抢到锁的线程会阻塞等待
import threading# 定义全局变量
g_num 0# 创建一个多线程互斥锁
lock threading.Lock()def sum_num1():global g_num# 循环一次给全局变量加1for i in range(1000000):# 抢到锁代码可以继续向下执行否则就会阻塞等待lock.acquire() # 抢锁g_num 1lock.release() # 释放锁print(sum1, g_num)def sum_num2():global g_num# 循环一次给全局变量加1for i in range(1000000):# 抢到锁代码可以继续向下执行否则就会阻塞等待lock.acquire() # 抢锁g_num 1lock.release() # 释放锁print(sum2, g_num)if __name__ __main__:# 创建两个线程first_thread threading.Thread(targetsum_num1)second_thread threading.Thread(targetsum_num2)# 启动两个线程first_thread.start()second_thread.start()# 阻塞等待主线程等待子线程结束再向下运行first_thread.join()second_thread.join()print(g_num)四. 资源共享的注意点
线程的资源共享问题只存在于低版本的Python解释器比如3.6.53.10已解决当多个线程同时操作同一个共享的全局变量时可能会造成错误的结果解决办法如下
线程同步保证同一时刻只能有一个线程去操作共享资源(全局变量) 线程等待thread.join() 让一个线程完全执行结束再去执行另一个线程缺点一个执行完再执行另一个和单任务几乎没有区别 互斥锁 多个线程去抢同一把锁threading.Lock()抢到锁的线程执行没抢到锁的线程会阻塞等待。缺点虽然保障程序执行的多任务如果频繁的加锁、释放锁会额外增加执行的时间消耗 从场景下手不用多线程做累加count操作只做append操作
五. 进程线程对比
进程是操作系统资源分配的基本单位线程是CPU调度的基本单位。线程不能够独立执行必须依存在进程中。创建进程的资源开销要比创建线程的资源开销要大。进程之间不共享全局变量线程之间共享全局变量但是在低版本的Python中要注意线程资源竞争的问题。进程稳定性高适合计算密集型任务线程适合IO密集型任务目前Python多线程不能利用CPU多核心优势想利用CPU多核心的优势Python只能采用多进程