(七)信号,信号量,同步异步,锁,线程笔记

信号
一个进程向另一个进程通过信号传递某种讯息,接收方在接收到信号后进行相应的处理

查看信号:kill -l

kill -signum PID   给PID的进程发送一个信号

 import os
from time import sleep
while True:
    sleep(2)
    print("Running the process",os.getpid())
# 另开一个终端输入  kill -信号 PID

关于信号
信号名称:信号的名字或者数字
信号含义:信号的作用
默认行为:当一个进程接收到信号时采取的行为
        终止进程,暂停进程,忽略产生

e.g.
SIGHUP     终端断开
SIGINT     ctrl + c
SIGQUTT         ctrl + \
SIGTSTP         ctrl + z
SIGKILL          终止进程且不能被处理
SIGSTOP     暂停进程且不能被处理
SIGALRM  时钟信号
SIGCHLD  子进程状态改变发给父进程

通过python进行信号处理

os.kill(pid,sig)
功能:发送信号给某个进程
参数:pid 给哪个进程发送信号
     sig 要发送什么信号

import os
import signal
os.kill(12154,signal.SIGKILL)# 表示给12154发送SIGKILL
os.kill(os.getppid(),signal.SIGALRM)# 给父进程发送信号

signal.alarm(sec)
功能:一定时间后给自身发送一个SIGALRM信号
参数:指定时间

* 一个进程中只能设置一个时钟,第二个时钟会覆盖之前的时间

import signal
import time
signal.alarm(3) # 3秒后向自身发送SIGALRM信号
while True:
    time.sleep(1)
    print("等待时钟信号......")

程序执行的同步和异步
同步:按照步骤一步一步顺序执行
异步:在程序执行中利用内核,不影响应用层程序持续执行

*信号是唯一的异步通信方式

signal.pause()
功能:阻塞等待一个信号的发生

import signal
import time
signal.alarm(5)
signal.pause()
while True:
    time.sleep(1)
    print("等待时钟信号......")

signal.signal(signum,handler)
功能:处理信号
参数:signum 要处理的信号
     handler 信号的处理方法
        SIG_DFL 表示使用默认的方法处理
        SIG_IGN 表示忽略这个信号
        func  自定义函数处理信号
            def func(sig,frame):
                pass
            sig 表示要处理的信号
            frame 信号的结构对象

* signal函数是一个异步处理函数
* signal函数不能处理SIGKILL SIGSTOP信号
* 在父进程中使用signal(SIGCHLD,SIG_IGN),这样子进程退出是会有系统自动处理

import signal
from time import sleep
signal.alarm(5)
signal.signal(signal.SIGALRM,signal.SIG_DFL)# 使用默认方法处理SIGALRM信号
signal.signal(signal.SIGINT,signal.SIG_IGN)#忽略ctrl + c
while True:
    sleep(2)
    print("让你忽略ctrl+c")
    print("等待时钟.....")
from signal import * 
import time 
#信号处理函数
def handler(sig,frame):
    if sig == SIGALRM:
        print("接收到时钟信号")
    elif sig == SIGINT:
        print("就不结束")
alarm(5)
#当接收到SIGALRM信号 用handler函数处理
signal(SIGALRM,handler)
signal(SIGINT,handler)
while True:
    print("Waiting for a signal")
    time.sleep(2)

信号量
给定一定的数量,对多个进程可见,并且多个进程根据信号量的多少确定不同的行为

multiprocessing  ---> Semaphore()

sem = Semaphore(num)
功能:生成信号量对象
参数:信号量的初始值
返回值:信号量对象

sem.acquire() 信号量数量减1 信号量为0时会阻塞
sem.release() 信号量数量加1
sem.get_value() 获取当前信号量的值

from multiprocessing import Semaphore,Process 
from time import sleep 
import os 
sem = Semaphore(3)#创建信号量 初始 3
def fun():
    print("进程 %d 等待信号量"%os.getpid())
    sem.acquire() #消耗一个信号量
    print("进程 %d 消耗信号量"%os.getpid())
    sleep(3)
    print("进程 %d 添加信号量"%os.getpid())
    sem.release()
jobs = []
for i in range(4):
    p = Process(target = fun)
    jobs.append(p)
    p.start()
for i in jobs:
    i.join()
print(sem.get_value())

同步互斥机制

目的:解决对共有资源操作产生的争夺

临界资源:多个进程或者线程都能够操作的资源
临街区:操作临界资源的代码段

同步:是一种合作关系,为完成某个任务,多进程或者多线程之间形成一种协调。按照约定依次执行对临界资源的操作,相互告知相互促进。
互斥:互斥是一种制约关系,当一个进程占有临界资源就会进行加锁操作,此时其他进程就无法操作该临界资源。直到使用的进程进行解锁操作后才能使用

Event 事件

multiprocessing --> Event

创建事件对象
e = Event()

事件阻塞
e.wait([timeout])

事件设置
e.set()
功能:当e被set()后e.wait()不再阻塞

事件清除
e.clear()
功能:当e被clear()后e.wait()又会阻塞

事件判断 判断当前事件对象是否被设置
e.is_set()

from multiprocessing import Event
e = Event()# 创建事件对象
e.set()#设置事件
e.wait(5)
print("===========")
print(e.is_set())
e.clear()
e.wait()

锁 Lock

multiprocessing --> Lock

创建对象
lock = Lock()

lock.acquire() 上锁
lock.release() 解锁

上锁状态 : 执行acquire()操作会阻塞
解锁状态 : 执行acquire()不阻塞

with lock:  ---> 上锁
    ...
    ...    ---> with代码段结束即解锁

两种锁效果一样

from multiprocessing import Process,Lock
import sys
from time import sleep
# sys.stdout 为共享资源所有进程都可以操作
def writer1():
    lock.acquire() # 上锁
    for i in range(5):
        sleep(1)
        sys.stdout.write("人生苦短\n")
    lock.release() # 解锁
def writer2():
    with lock: #with方式上锁
        for i in range(5):
            sleep(1)
            sys.stdout.write("我用Python\n")
lock = Lock()       
w1 = Process(target = writer1)
w2 = Process(target = writer2)
w1.start()
w2.start()
w1.join()
w2.join()

线程

什么是线程
线程也是一种多任务编程的方式,可以使用计算机多核资源。线程又被称为轻量级的进程

线程特征
* 线程是计算机核心分配的最小单位
* 一个进程可以包含多个线程
* 线程也是一个运行过程,也要消耗计算机资源。多个线程共享其进程的资源和空间
* 线程也拥有自己特有的资源属性,比如指令集,TID等
* 线程无论创建还是删除还是运行,资源消耗都小于进程
* 多个线程之间并行执行,互不干扰

threading 模块创建线程

threading.Thread()
功能:创建线程对象
参数:name 线程名称
     target 线程函数
     args 元组 给线程函数传参
     kwargs 字典 给线程函数传参

t.start() 启动线程
t.join([timeout]) 回收线程

import threading
from time import sleep
import os
a = 1
# 线程函数
def music():
    global a
    a = 10000
    for i in range(5):
        sleep(2)
        print("播放葫芦娃",os.getpid())
# 创建线程对象
t = threading.Thread(target = music)
t.start()
for i in range(5):
    sleep(1.5)
    print("想听扶摇",os.getpid())
t.join()

print("a = ",a)#a = 10000

线程属性
t.is_alive() 查看线程状态
t.name 线程名称
t.setName() 设置线程名称
threading.currentThread() 获取当前线程对象

from threading import Thread,currentThread
from time import sleep
# 线程函数
def fun(sec):
    print("线程属性测试")
    sleep(sec)
    #获取线程对象 getName()获取名字
    print("%s 线程结束" % currentThread().getName())
thread = []
for i in range(3):
    t = Thread(target = fun,name = "tedu%d"%i,args = (3,))
    thread.append(t)
    t.start()
    print(t.is_alive()) # 查看进程状态
thread[1].setName('Tarena')#查看线程名称
print(thread[2].name)
for i in thread:
    i.join()


t.daemon
默认情况下,主线的结束不会影响分支线程,如果设置为True则主线程退出分支线程也会退出

设置方法
t.daemon = True
t.setDaemon(True)

判断daemon属性
t.isDaemon()

* 线程daemon属性的设置在start前
* 一般设置daemon后不会再使用join

from threading import Thread
from time import sleep
def fun():
    sleep(3)
    print("daemon 测试")
t = Thread(target = fun)
t.setDaemon(True)
print(t.isDaemon()) # 查看daemon属性
t.start()
print("======main thread over ======")

创建自己的线程类

1.继承Thread类
2.运行Thread类中的__init__方法以获取父类属性
3.重写run方法

from threading import Thread
from time import ctime,sleep
# 创建自己的线程类
class MyThread(Thread):
    def __init__(self,target,name = "Tedu",args = (),kwargs = {}):
        super().__init__()
        self.name = name
        self.target = target
        self.args = args
        self.kwargs = kwargs
    def run(self):
        self.target(*self.args,**self.kwargs)
# 线程事件
def player(song,sec):
    for i in range(2):
        print("Playing %s : %s" % (song,ctime()))
        sleep(sec)
t = MyThread(target = player,args = ('凉凉',3))
#自动执行run()
t.start()
t.join()

猜你喜欢

转载自blog.csdn.net/zh__quan/article/details/81070048