计算机的五大组成部分
控制器
运算器
输入设备
输出设备
cpu(控制器+运算器=中央处理器)
程序要想被计算机运行,代码必须要先由硬盘读到内存,之后取值在执行多道技术单核实现并发的效果
并发:看起来像同时运行的就可以称之为并发
并行:真正意义上的同时执行
ps:并行肯定是并发单核计算机肯定不能实现并行,但是可以实现并发
程序与进程的区别
程序就是一堆躺在评判上的代码,是“死”的
进程则表示进程正在执行,是“活”的
进程调度先来先服务调度算法:对长作业有利
短作业优先调度算法:对短作业有利
重要概念
同步和异步
’‘’描述的是任务的提交方式‘’‘
同步:任务提交以后,原地等待任务的返回结果,等待的过程中不做任何事(干等) 程序层面上表现出来的感觉是卡住了
异步:任务提交以后,不愿地等待任务的返回结果,直接去做其他事情
任务的返回会有一个异步回调机制的自动处理
阻塞非阻塞‘’‘描述的是程序的运行状态’‘’
阻塞:
阻塞态
非阻塞:
就绪态,运行态
理想状态:代码永远处于就绪态和运行态之间切换最高效的是异步非阻塞(例如go框架)
开启进程两种方式代码开启进程和线程的方式,代码书写基本是一样的总结:创建进程就是在内存中申请一块内存空间将需要运行的代码丢进去一个进程对应在内存中就是一块独立的内存空间多个进程对应在内存就是多块内存空间进程与进程之间数据默认情况下是无法直接交互的,如果想交互可以借助第三方工具,模块
进程数据相互隔离
from multiprocessing import Process
money=100
def task():
global money
money=666
print(money)
if __name__ == '__main__':
p=Process(target=task)
p.start()
p.join()
print(money)
开启进程方法
from multiprocessing import Process
import time
def task(name):
print('{} is running'.format(name))
time.sleep(3)
print('{} is over'.format(name))
if __name__ == '__main__':
#1、创建一个对象
p=Process(target=task,args=('lz',))
#容器类型哪怕里面只有1个元素,建议要用逗号隔开
#2、开启进程
p.start()
print('=======')
守护进程
from multiprocessing import Process
import time
def fask(name):
print('{}live'.format(name))
time.sleep(3)
print('{}dead'.format(name))
if __name__ == '__main__':
p = Process(target=fask,args=('hh',))
p.daemon=True#将进程p设置为守护进程,一定要放到start方法上面
p.start()
print('正常dead')
注意
字典取值不要用【】(若取的值不存在会报错),推荐使用get
互斥锁
多个进程操作同一份数据的时候,会出现数据错乱的问题
针对上述问题,解决方法就是加锁处理:将并发变成串行,牺牲效率但是保证了数据的安全
from multiprocessing import Process, Lock
import json
import time
import random
def seacher(i):
# 文件操作读取票数
with open('data', 'r', encoding='utf8') as f:
dic = json.load(f)
print(
'用户%s查询余票%s' % (i, dic.get('ticket_num')))
# 字典取值不要用【】(若取的值不存在会报错),推荐使用get
# 买票 1、先查 2、再买
def buy(i):
# 先查票
with open('data', 'r', encoding='utf8') as f:
dic = json.load(f)
# 模拟网络延迟
time.sleep(random.randint(1, 3))
# 判断当前是否有票
if dic.get('ticket_num') > 0:
# 修改数据库 买票
dic['ticket_num'] -= 1
# 写入数据库
with open('data', 'w',
encoding='utf8') as f:
json.dump(dic, f)
print('用户%s买票成功' % i)
else:
print('用户%s买票失败' % i)
def run(i,mutex):
seacher(i)
#给买票环节加锁处理
mutex.acquire() #抢锁
buy(i)
#释放锁
mutex.release()
if __name__ == '__main__':
#在主进程中生成一把锁,让所有的子进程抢,谁先抢到谁先买票
mutex=Lock()
for i in range(1, 11):
p = Process(target=run, args=(i,mutex))
p.start()
'''
注意:
1、锁不要轻易的使用,容易造成死锁现象
2、锁只在处理数据的部分加来保证数据的安全(只在争抢数据的环节加锁处理即可)
'''
进程间通信
队列queue
'''
队列:先进先出
堆栈:先进后出
'''
IPC机制
from multiprocessing import Process,Queue
'''
研究思路:
1、主进程跟子进程借助于队列通信
2、子进程跟子进程借助于队列通信
'''
def producer(q):
q.put('hello beautiful girl ')
def consumer(q):
print(q.get())
if __name__ == '__main__':
q=Queue()
p = Process(target=producer,args=(q,))
p1 = Process(target=consumer,args=(q,))
p.start()
p1.start()
线程理论
- 什么是线程
'''
进程:资源单位(车间)
线程:执行单位(流水线)
总结:
起一个进程仅仅只是在内存空间中开辟出一块独立的空间
真正被执行的其实是进程里面的线程,线程指的是代码的执行过程,执行代码中所需要使用到的资源都找所在的进程索要
进程和线程都是虚拟单位。只是为了我们更方便的描述问题
'''
为何要有线程
'''
开设进程
1、申请内存空间 耗资源
2、“拷贝代码” 耗资源
开线程
一个进程内可以开设多个线程,在一个进程内开设多个线程无需再次申请内存空间操作
总结:
开设线程的开销要远远小于进程的开销
同一个进程下的线程数据是共享的
'''