进程补充进程间的信号信号量(信号灯)进程的同步互斥Event事件Lock 锁
进程补充
进程间的信号
信号是唯一的异步通信方法
一个进程向另一个进程发送一个信号来传递某种信息,接受者根据传递的信息来做相应的事
$ kill -l
查看系统信号说明
$ kill -9 pid号
对进程发送信号
信号名称 | 说明 | | |
1) SIGHUP | 连接断开 | | |
2) SIGINT | ctrl+c | | |
3) SIGQUIT | ctrl+\ | | |
20) SIGTSTP | ctrl+z | | |
9) SIGKILL | 终止进程 | | |
19) SIGSTOP | 暂停进程 | | |
26) SIGVTALRM | 时钟信号 | | |
17) SIGCHLD | 子进程退出时给父进程发的信号 | | |
| | | |
在Python中import signal
可以获取信号
os.kill(pid, sig)
- 功能:发送信号
- 参数
- pid:要发送信号的PID号
- sig :信号名称
import os
import signal
os.kill(12345,signal.SIGKILL) #杀死进程
View Code
signal.alarm(time)
个人理解:把发送信号的信息告知系统内核,应用层程序继续运行,时间到之后利用内核告知应用层程序进行处理- 功能:非阻塞函数,向自身进程发送一个时钟信号
- 参数:time->整型时间秒
import signal
import time
signal.alarm(3)#3秒后向自身发送一个时钟信号
while True:
time.sleep(1)
print("等待时钟信号")
'''打印结果
等待时钟信号
等待时钟信号
闹钟
'''
- View Code
signal.alarm(3)#3秒后向自身发送一个时钟信号
time.sleep(2)
signal.alarm(5)#进程只有一个时钟信号,第二个会覆盖上面的时钟信号
while True:
time.sleep(1)
print("等待时钟信号")
'''打印结果
等待时钟信号
等待时钟信号
等待时钟信号
等待时钟信号
闹钟
'''
- View Code
signal.pause()
- 功能:阻塞进程,然后等待信号
signal.signal(signum, handler)
- 功能:处理信号
- 参数
- signum:要处理的信号
- handler:信号的处理方法
SIG_DFL
表示使用默认方法处理SIG_IGN
表示忽略这个信号function
表示传入一个函数,用指定的函数处理
- def function(sig, frame)
sig:捕获到的信号
frame:信号对象
View
import signal
from time import sleep
signal.alarm(5) # 5秒后向自身发送一个时钟信号
# 使用信号的默认方法处理
# signal.signal(signal.SIGALRM,signal.SIG_DFL)
# 忽略时钟信号
# signal.signal(signal.SIGALRM,signal.SIG_IGN)
# 忽略Ctrl+c信号
# signal.signal(signal.SIGINT,signal.SIG_IGN)
while True:
sleep(2)
print("等待时钟...")
View Code
# 使用自定义函数处理信号
import signal
from time import sleep
def fun1(sig, frame):
if sig == signal.SIGALRM :
print("接收到时钟信号")
elif sig == signal.SIGINT :
print("ctrl+c就不结束")
signal.alarm(5) # 5秒后向自身发送一个时钟信号
# 使用自定义函数处理信号
# 处理时钟信号
signal.signal(signal.SIGALRM,fun1)
# 处理ctrl+c信号
signal.signal(signal.SIGINT,fun1)
while True:
print("等待")
sleep(2)
'''打印结果
等待
等待
等待
接收到时钟信号
等待
...
'''
View Code
信号量(信号灯)
原理:给定一个数量对多个进程可见,且多个进程都可以操作,进程可以对数量多少的判断执行各自的行为
from multiprocessing import Semaphore
sem = Semaphore(num)
- 功能:创建信号量
- 参数:信号量的初始值
- 返回值:信号量的对象
sem.get_value()
:获取信号量的值sem.acquire()
:将信号量 -1,当信号为0时会阻塞sem.release()
:将信号量 +1
from multiprocessing import Semaphore, Process
# 创建信号量对象
sem = Semaphore(num)
def fun():
print("进程%d等待信号量"%os.getpid())
# 消耗一个信号量
sem.acquire()
print("进程%d消耗信号量"%os.getpid())
# 添加一个信号量
sem.release()
print("进程%d添加信号量"%os.getpid())
jobs = []
for i in range(4):
p = Process(target = 4)
jobs.append(p)
p.start()
for i in jobs:
i.join()
print(sem.get_value())
View Code
进程的同步互斥
临界资源:多个进程或者线程都能操作的共享资源
临界区:操作临界区资源的代码段
同步:同步是一种合作关系,为完成某个任务,多进程或者多线程之间形成的一种协调关系
互斥:互斥是一种制约关系,
Event事件
from multiprocessing import Event
-
e = Event()
:创建一个事件对象 -
e.wait([timeout])
:设置事件阻塞 -
e.set()
:事件设置,当事件被设置后e.wait()
不再阻塞,等于释放资源区 -
e.clear()
:清除设置,当事件被设置e.clear()
后,e.wait()
又会阻塞,阻塞资源区 -
e.is_set()
:事件状态判断,判断事件是否处于被设置的状态
from multiprocessing import Event
# 创建事件对象
e = Event()
# 查看
print(e.is_set()) # False
e.set()
print(e.is_set()) # True
e.wait(3)
print(e.is_set()) # True
e.clear()
print(e.is_set()) # False
View Code
from multiprocessing import Event,Process
from time import sleep
def wait_event1():
print("1想操作临界区资源")
e.wait()
print("1开始操作临界区资源",e.is_set())
with open("file") as f:
print(f.read())
def wait_event2():
print("2也想操作临界区资源")
# 超时3秒检测
e.wait(3)
# 判断是否被设置
if e.is_set():
print("2开始操作临界区资源",e.is_set())
with open("file") as f:
print(f.read())
else:
print("2不能操作")
# 创建事件对象
e = Event()
p1 = Process(target = wait_event1)
p2 = Process(target = wait_event2)
p1.start()
p2.start()
print("主进程操作")
with open("file",'w') as f:
f.write("HELLO WORD")
# 延迟4秒释放临界区
sleep(4)
# 释放临界区资源
e.set()
print("释放临界区")
p1.join()
p2.join()
View Code
Lock 锁
from multiprocessing import Lock
-
lock = Lock()
:创建一个锁对象 -
lock.acquire()
:上锁,如果已经是上锁状态,调用此函数会阻塞 -
lock.release()
:解锁
from multiprocessing import Lock,Process
import sys
def writer1():
# 上锁
lock.acquire()
for i in range(20):
sys.stdout.write("writer1111\n")
# 解锁
lock.release()
def writer2():
# 上锁
lock.acquire()
for i in range(20):
sys.stdout.write("writer2222\n")
# 解锁
lock.release()
lock = Lock()
w1 = Process(target = writer1)
w2 = Process(target = writer2)
w1.start()
w2.start()
w1.join()
w2.join()
View Code
第二种方法
使用with
语句上锁,with语句执行完毕后会自动解
with lock:
.....
.....