操作系统——进程相关

一、进程相关(状态、同步、异步、阻塞、非阻塞)

1、状态介绍

	在程序运行的过程中,由于被操作系统的调度算法控制,程序会进入几个状态:就绪,运行和阻塞。

	(1)就绪(Ready)状态当进程已分配到除CPU以外的所有必要的资源,只要获得处理机便可立即执行,这时的进程状态称为就绪状态。

	(2)执行/运行(Running)状态当进程已获得处理机,其程序正在处理机上执行,此时的进程状态称为执行状态。

  (3)阻塞(Blocked)状态正在执行的进程,由于等待某个事件发生而无法执行时,便放弃处理机而处于阻塞状态。引起进程阻塞的事件可有多种,例如,等待I/O完成、申请缓冲区不能满足、等待信件(信号)等。

2、同步和异步

2、1同步

	所谓同步就是一个任务的完成需要依赖另外一个任务时,只有等待被依赖的任务完成后,依赖的任务才能算完成,这是一种可靠的任务序列。要么成功都成功,失败都失败,两个任务的状态可以保持一致。

2、2异步

	所谓异步是不需要等待被依赖的任务完成,只是通知被依赖的任务要完成什么工作,依赖的任务也立即执行,只要自己完成了整个任务就算完成了。至于被依赖的任务最终是否真正完成,依赖它的任务无法确定,所以它是不可靠的任务序列。

3、阻塞和非阻塞

3、1阻塞、非阻塞描述

	阻塞和非阻塞这两个概念与程序(线程)等待消息通知(无所谓同步或者异步)时的状态有关。也就是说阻塞与非阻塞主要是程序(线程)等待消息通知时的状态角度来说的	

3、2同步阻塞、异步阻塞、同步非阻塞、异步非阻塞形式

老张爱喝茶,废话不说,煮开水。

出场人物:老张,水壶两把(普通水壶,简称水壶;会响的水壶,简称响水壶

)。

1 老张把水壶放到火上,立等水开。(同步阻塞)

老张觉得自己有点傻

2 老张把水壶放到火上,去客厅看电视,时不时去厨房看看水开没有。(同步非阻塞)

老张还是觉得自己有点傻,于是变高端了,买了把会响笛的那种水壶。水开之后,能大声发出嘀~~~~的噪音。

3 老张把响水壶放到火上,立等水开。(异步阻塞)

老张觉得这样傻等意义不大

4 老张把响水壶放到火上,去客厅看电视,水壶响之前不再去看它了,响了再去拿壶。(异步非阻塞)

老张觉得自己聪明了。

所谓同步异步,只是对于水壶而言。

普通水壶,同步;响水壶,异步。

虽然都能干活,但响水壶可以在自己完工之后,提示老张水开了。这是普通水壶所不能及的。

同步只能让调用者去轮询自己(情况2中),造成老张效率的低下。

所谓阻塞非阻塞,仅仅对于老张而言。

立等的老张,阻塞;看电视的老张,非阻塞。

情况1和情况3中老张就是阻塞的,媳妇喊他都不知道。虽然3中响水壶是异步的,可对于立等的老张没有太大的意义。所以一般异步是配合非阻塞
使用的,这样才能发挥异步的效用。

二、创建进程的多种方式

# coding:utf-8
'''
1、鼠标双击应用程序、创建进程
2、Python代码创建进程
'''
'''
在不同的操作系统种,创建进程的底层的原理不一样
    windows
        已导入模块的形式创建进程
    MAC/Linux
        以copy代码的形式创建进程
'''
from multiprocessing import Process
import time


def task(name):
    print('task is running', name)
    time.sleep(3)
    print('task is over!', name)


if __name__ == '__main__':
    # target 需要创建的子进程的函数名
    # arg 函数需要传入的参数,逗号不可少
    p1 = Process(target=task, args=('子进程',))
    # 异步,告诉操作系统创建一个新的进程,并在子进程中执行函数task
    p1.start()
    # 异步,在创建子进程的同时,主进程继续在执行
    print('主进程')


class MyProcess(Process):
    def __init__(self, name, age):
        super().__init__()
        self.name = name
        self.age = age

    def my_school(self, school, grade):
        self.school = school
        self.grade = grade

    def run(self):
        print('run is running', self.name, self.age, self.school, self.grade)
        time.sleep(3)
        print('run is over', self.name, self.age, self.school, self.grade)


if __name__ == '__main__':
    obj = MyProcess('lu_yao', '23')
    obj.my_school('中国科学院', '六年级')
    obj.start()
    print('主函数')

三、进程间数据隔离

'''
同一台计算机上的多个进程数据是严格意义上的物理隔离(默认情况下)
'''
# coding:utf-8
from multiprocessing import Process
import time
'''
同一台计算机上的多个进程数据是严格意义上的物理隔离(默认情况下)
'''
money = 1000


def task():
    # global 添加的全局变量可以在函数体内被修改
    global money
    # 在函数体内对money进行了重新赋值
    money = 666
    print('子进程的money>>>:', money)  # 子进程的money>>>: 666


if __name__ == '__main__':
    p1 = Process(target=task)
    # 输出函数体内修改过的money 666
    p1.start()  # 子进程的money>>>: 666
    time.sleep(3)
    #  就算在函数体内对money进行了重新赋值
    #  但是因为是一个子进程,只修改了子进程里的数据
    print('主进程的money>>>:', money) # 主进程的money>>>: 1000

四、进程的join方法

'''
join()方法的作用是,等待子进程接收后再执行主进程
'''
# coding:utf-8
from multiprocessing import Process
import time


def task(name, n):
    print('%s is running!' % name)
    time.sleep(n)
    print('%s is over!' % name)


if __name__ == '__main__':
    '''
    输出结果:
    lu_yao is running!
    lu_yao is over!
    主进程
    '''
    p1 = Process(target=task, args=('lu_yao', 1))
    p1.start()
    p1.join()
    print('主进程')

五、IPC机制(进程间的通信)(Queue模块)

'''
	IPC(Inter-Process Communication,进程间通信)。进程间通信是指两个进程的数据之间产生交互
	消息队列:存储数据的地方 所有人都可以存 也都可以取
'''
# coding:utf-8
from multiprocessing import Process, Queue
# Queue() 括号内填写可以存储数据的个数
message_queue = Queue(3)
# 向消息队列中存放数据
message_queue.put(111)
message_queue.put(222)
# 判断队列是否已满
print(message_queue.full())
message_queue.put(333)
print(message_queue.full())
# 从消息队列中取出数据
print(message_queue.get())
print(message_queue.get())
# 判断队列是否为空
print(message_queue.empty())
print(message_queue.get())
"""
full() empty() 在多进程中都不能使用!
"""

5.1 Queue实战

from multiprocessing import Process, Queue


def product(message_queue):
    message_queue.put('子进程添加的数据!')


def consumer(message_queue):
    print('子进程获取队列中的数据>>>:', message_queue.get())


if __name__ == '__main__':
    message_queue = Queue()
    p1 = Process(target=product, args=(message_queue,))
    p2 = Process(target=consumer, args=(message_queue,))
    p1.start()
    p2.start()
    print('主函数')

六、进程对象的多种方法

# coding:utf-8
# 如何查看进程号
from multiprocessing import Process, current_process
import time
# print(current_process())
# print(current_process().pid)
'''
输出结果:
    <_MainProcess name='MainProcess' parent=None started>
    31528  
'''


# 终止进程
def product():
    print('子进程')


if __name__ == '__main__':
    p1 = Process(target=product)
    p1.start()
    # time.sleep(1)
    p1.terminate()  # 杀死进程
    print('主进程')
    # 判断进程是否存活
    time.sleep(3)
    print(p1.is_alive())

七、守护进程

'''
守护进程会随着守护的进程结束而立刻结束
'''
# coding:utf-8
from multiprocessing import Process
import time


def task(name):
    print('子程序>>>:%s' % name)
    time.sleep(3)
    print('子程序>>>:%s' % name)


if __name__ == '__main__':
    '''
    (1)如果某个子线程的daemon属性为False,
    主线程结束时会检测该子线程是否结束,
    如果该子线程还在运行,则主线程会等待它完成后再退出;
    (2)如果某个子线程的daemon属性为True,
    主线程运行结束时不对这个子线程进行检查而直接退出,
    同时所有daemon值为True的子线程将随主线程一起结束,
    而不论是否运行完成。
    '''
    p1 = Process(target=task, args=('子程序',))
    p1.daemon = True
    p1.start()
    time.sleep(1)
    print('主程序')

八、僵尸进程与孤儿进程

僵尸进程
	进程执行完毕后并不会立刻销毁所有的数据 会有一些信息短暂保留下来
 	比如进程号、进程执行时间、进程消耗功率等给父进程查看
 	ps:所有的进程都会变成僵尸进程
孤儿进程
	子进程正常运行 父进程意外死亡 操作系统针对孤儿进程会派遣福利院管理

九、多进程数据错乱问题

模拟抢票软件

from multiprocessing import Process
import time
import json
import random


# 查票
def search(name):
    with open(r'data.json', 'r', encoding='utf8') as f:
        data = json.load(f)
    print('%s在查票 当前余票为:%s' % (name, data.get('ticket_num')))


# 买票
def buy(name):
    # 再次确认票
    with open(r'data.json', 'r', encoding='utf8') as f:
        data = json.load(f)
    # 模拟网络延迟
    time.sleep(random.randint(1, 3))
    # 判断是否有票 有就买
    if data.get('ticket_num') > 0:
        data['ticket_num'] -= 1
        with open(r'data.json', 'w', encoding='utf8') as f:
            json.dump(data, f)
        print('%s买票成功' % name)
    else:
        print('%s很倒霉 没有抢到票' % name)


def run(name):
    search(name)
    buy(name)


if __name__ == '__main__':
    for i in range(10):
        p = Process(target=run, args=('用户%s'%i, ))
        p.start()
   
"""
多进程操作数据很可能会造成数据错乱>>>:互斥锁
	互斥锁
		将并发变成串行 牺牲了效率但是保障了数据的安全
"""

原文地址:http://www.cnblogs.com/HaiMan/p/16904184.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性