zoukankan      html  css  js  c++  java
  • Python网络编程(进程通信、信号、线程锁、多线程)

    什么是进程通讯的信号?
    用过Windows的我们都知道,当我们无法正常结束一个程序时,
    可以用任务管理器强制结束这个进程,但这其实是怎么实现的呢?
    同样的功能在Linux上是通过生成信号和捕获信号来实现的,
    运行中的进程捕获到这个信号然后作出一定的操作并最终被终止。
    信号是UNIX和Linux系统响应某些条件而产生的一个事件,
    接收到该信号的进程会相应地采取一些行动。通常信号是由一个错误产生的。
    但它们还可以作为进程间通信或修改行为的一种方式,
    明确地由一个进程发送给另一个进程。一个信号的产生叫生成,接收到一个信号叫捕获
    什么是线程锁?
            1.在单一进程的情况下可以叫单进程也可以叫单线程
             2.线程锁的大致思想是:如果线程A和线程B会执行实例的两个函数a和b
    如果A必须在B之前运行,那么可以在B进入b函数时让B进入wait

    set,直到A执行完a函数再把B从wait set中激活。这样就保证了B必定在A之后运行,无论在之前它们的时间先后顺序是怎样的。

            3. 线程锁用于必须以固定顺序执行的多个线程的调度

    线程锁的思想是先锁定后序线程,然后让线序线程完成任务再解除对后序线程的锁定。

    信号:
        一个进程通过信号的方式传递某种讯息,
        接收方收到信号后作出相应的处理
        kill -sig pid:通过pid发送信号杀死指定进程
        kill -l:查看操作系统内所所有sig信号
    关于信号:
        信号名称: 系统定义,名字或数字
        信号含义:系统定义,信号的作用
        默认处理方法:
              当一个进程接收到信号时,默认产生的效果
      进程终止、暂停进程、忽略法发生
        SIGHUP:    断开链接
        SIGINT:      Ctrl + c
        SIGQUIT:    Ctrl +
        SIGTSTP :   Ctrl + z
        SIGKILL:     终止进程且不能被处理
        SIGSTOP:   暂停进程且不能被处理
        SIGALRM:  时钟信号
        SIGCHLD:  子进程改变状态时父进程会收到此信号
     
    Python信号处理:(signal模块)
        os.kill(pid,sig)
          功能:
      发送一个信号给某个进程
          参数:
              pid:给那个进程发送信号(进程pid)
      sig:要发送的信号类型
        signal.alarm(sec)
           功能:
              异步执行
              设置时钟信号
      在一定时间后给自己发送一个SIGALRM信号
      一个进程只能挂起一个时钟
      重新挂起时钟会覆盖之前时钟
           参数:
              sec:时间(秒)
        signal.pause()
            功能:
       阻塞进程,等待一个信号
        signal.signal(sig,handler)
            功能:信号处理
    参数:
       sig:要处理的信号
       handler:信号处理方法
           可选值:
              SIG_DFL  表示使用默认方法处理
      SIG_IGN  表示忽略这个信号
      func     自定义函数
           自定义函数格式:
                 def func(sig,frame):
            sig:收到的信号
    frame:信号结构对象
            signal函数也是一个异步处理函数,只要执行了该函数
    则进程任意时候接受到相应的信号都会处理
    signal是不能处理SIGKILL 、SIGSTOP的
    父进程中可以使用 signal(SIGCHLD,SIG_IGN)
    将子进程的退出交给系统处理
     
    程序的异步同步执行:
        (单进程的同步异步)
        同步:
           程序按照步骤一步步执行,呈现一个先后性的顺序
        异步:
           信号是唯一一个内部通信方式
           程序在执行中利用内核功能帮助完成必要的辅助操作
           不影响应用层的持续执行
           信号是一种异步的进程间通讯方法
     
    示例:

    from signal import * 
    import time 
    
    def handler(sig,frame):  # 自定义处理信号
        if sig == SIGALRM:  # 判断信号类型
            print("收到时钟信号")
        elif sig == SIGINT:
            print("就不结束 略略略~")
    
    alarm(5)  # 设置5秒时钟信号
    
    signal(SIGALRM,handler)
    signal(SIGINT,handler)  #  Ctrl + C
    
    while True:
        print("Waiting for a signal")
        time.sleep(2)
     
     
    信号量:
        给定一定的数量,对多个进程可见,
        并且多个进程根据信号量的多少确定不同行为
     
        sem = Semaphore(num)
            功能:创建信号量
    参数:信号量初始值
    返回值:信号量对象
        sem.acquire()
            将信号数量减1  当数量为0时阻塞
        sem.release()
            将信号量加1
        sem.get_value()
            获取当前信号量的值(数量)
     
    同步互斥机制
        目的:
           解决对共有资源产生的资源争夺
        临界资源:
             多个进程或线程都可以操作的资源
        临界区:
            操作临界资源的代码段
        同步:
            同步是一种合作关系,为完成某个任务,
    多进程或者多个线程之间形成的一种协调
    按照约定执行,相互告知,共同完成任务
        互斥:
            互斥是一种制约关系,当一个进程或者线程
    进入临界区操作资源时采用上锁的方式,
    阻止其他进程操作,直到解锁后才能让出资源
     
    Event事件:
      from multiprocessing import Event
      创建事件对象
          e = Event()
      事件阻塞
          e.wait([timeout])
            功能:
       使进程处于阻塞状态,直到事件对象被set
      事件设置:
          e.set.()
             功能:
       让事件对象变为被设置状态
      清除设置:
          e.clear()
             功能:使事件对象清除设置状态
      事件判断:
          e.is_set()
            判断当前事件是否被set
     
    示例:
     

    from multiprocessing import Process,Event 
    from time import sleep
    
    def wait_event(file):
        print("准备操作临界资源")
        e.wait()  # 等待主进程执行结束后set
        print("开始操作临界资源",e.is_set())
        fw = open('1.jpg','wb')
        with open(file,'rb') as f:  # 复制图片
            fw.write(f.read())
    
    def wait_event_timeout(file):
        print("也想操作临界资源")
        e.wait(2)  # 等待主进程执行set并进行2秒超时检测
        if e.is_set():
            print("也开始操作临界资源")
            fw = open('2.jpg','wb')
            with open(file,'rb') as f:  # 复制图片
                fw.write(f.read())
        else:
            print("等不了了,不等了")
    # 创建事件
    e = Event()
    path = "/home/tarena/file.jpg"
    file = 'file.jpg'
    
    # 创建两个进程分别复制两个图片
    p1 = Process(target = wait_event,args = (file,))
    p2 = Process(target = wait_event_timeout,args = (file,))
    
    p1.start()
    p2.start()
    
    # 主进程先复制图片 让子进程进入wait状态
    print("主进程在操作临界资源")
    sleep(3)
    fw = open(file,'wb')
    with open(path,'rb') as f:
        fw.write(f.read())
    fw.close()
    e.set()  # 子进程set
    print("主进程操作完毕")
    
    
    p1.join()
    p2.join()


    锁 Look
    multiprocessing --> Look
      创建对象:
          Lock = Lock()
      lock.acquire() 上锁
      lock.release()      解锁
      如果一个锁对象已经被上锁再调用则会阻塞
     
    multiprocessing 创建的子进程不能用input  会报错
     
    示例:
    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("writer1输出
    ")
        lock.release() #解锁
    # 虽然都sleep1秒但是 若不加锁会每1秒打印两次
    # 由于上锁原因 w1执行完临界区w2才能被执行 一秒一次
    def writer2():
        with lock:
            for i in range(5):
                sleep(1)
                sys.stdout.write("writer2输出
    ")
    
    #创建锁
    lock = Lock()
    
    w1 = Process(target = writer1)
    w2 = Process(target = writer2)
    
    w1.start()
    w2.start()
    
    w1.join()
    w2.join()


     
    多线程:
        什么是线程(thread
          线程也是一种多任务编程方式,可以使用计算机的多核资源
          线程被称为轻量级的进程
         线程的特征:
          1.一个进程可以包含多个线程
          2.线程是计算机内核使用的最小单位
          3.线程也是一个运行过程,也要消耗计算机资源
          4.多个线程共享共用进程的资源
          5.线程也有自己的特征属性,TID、指令集、线程栈
          6.多个线程之间独立运行互不干扰 空间不独立(都消耗进程空间)
          7.线程的创建删除消耗的资源要小于进程 线程/进程(1/20
     
    threading 模块
      threshold.Thread()
        功能:
           创建线程对象
        参数:
           target   线程函数
           name    线程名 默认为Thread-1...
           args      元组给线程函数位置传参
           kwargs  字典给线程函数键值传参
        返回值:
           线程对象
      t.start() 启动线程
      t.join()  回收线程
     
      线程对象属性:
          t.name 线程名
          t.setName() 设置线程名称
          t.is_alive()查看线程状态
          threading.currentThread() 获取当前进程对象
          t.daemon属性
              默认False主线程的退出不会影响分支线程的执行
      设置为True时主线程退出分支线程也退出
    设置daemon值
      t.setDaemon(True)
      t.daemon = True
    查看daemon值
      t.isDaemon
     
    创建自己的线程类;
       1.继承Thread
       2.加载父类__init__
       3.重写run
     
    示例:
        
    from threading import Thread 
    from time import sleep, ctime
    
    # 创建一个MyThread类继承Thread
    class MyThread(Thread):
        def __init__(self, target, name = "Tedu", args = (), kwargs = {}):
            super().__init__()  # 重新加载父类的__init__初始化方法
            self.target = target 
            self.name = name
            self.args = args
            self.kwargs = kwargs
    
        def run(self):  # 在创建对象时自动调用run方法
    # 在调用run时调分支线程要执行的线程函数  以*元组和**字典的方式接收万能传参
            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))
    t.start()
    t.join()

    
    
  • 相关阅读:
    js判断当前年龄
    获取手机号归属地
    关于vscode控制tab控制缩进2/4个空格
    vue中的 mvvm
    关于前端性能优化
    js 深拷贝
    关于js hasOwnPropetry // instanceof 整理
    node-sass 安装报错
    JS发送跨域Post请求出现两次请求的解决办法
    Vue面试复习
  • 原文地址:https://www.cnblogs.com/ParisGabriel/p/9479088.html
Copyright © 2011-2022 走看看