• 网络编程(七)


    前情回顾:

    1.进程间通信

    管道 Pipe recv send
    消息队列 Queue get put qsize full empty
    共享内存 效率高 Value shm.value Array shm迭代
    信号 : 异步通信 kill alarm pause
    信号量 套接字

    2. 进程池 Pool apply_async apply close join
    map

    3. 创建进程类 重写run

    ***********************************************
    信号处理 :

    signal.signal(signum,handler)
    功能 : 处理一个信号
    参数 : signum : 要处理的信号
    handler : 对该信号的处理方法
    SIG_DFL 采用默认方法
    SIG_IGN 忽略这个信号
    func 自定义的方法处理
    func 格式要求

    def func(sig,frame):
    ....
    sig : 接收到的信号
    frame : 信号对象


    * signal函数是一个异步处理信号函数,只要执行,在进程中就会按照指定方法处理信号
    * signal 不能处理 SIGSTOP SIGKILL信号


    信号量 : 给定一定的信号数量,对多个进程可见,并且多个进程均可操作。进程根据信号量的多少,可以有不同的行为

    multiprocess ----》 Semaphore()

    sem = Semaphore(num)
    功能 : 定义信号量
    参数 : num : 给定信号量的初始个数
    返回值 : 返回信号量对象

    sem.acquire() 将信号量 减一 信号量为0时调用会阻塞

    sem.release() 将信号量 加一

    cookie :

    获取当前进程对象
    multiprocssing.current_process()

    使用处理僵尸进程
    在父进程中,忽略子进程的发送信号
    signal(SIGCHLD,SIG_IGN)


    同步和互斥

    目的 : 对共有资源的操作会产生争夺,同步互斥是一种解决争夺的方案

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

    同步 : 同步是一种合作关系,为完成某个任务多进程或者多线程之间形成一种协调 ,按照条件次序执行,传递告知资源情况。 这种协调可能是因为阻塞关系达成的

    互斥 :互斥是一种制约关系,但一个进程或线程进入到临界区会进行加锁操作,此时其他进程(线程)在企图操作临界资源就会阻塞。只有当资源被释放才能进行操作

    Event 事件

    创建 事件对象
    e = Event()

    提供事件阻塞
    e.wait()

    对事件对象进程设置,此时wait判断如果事件被set则结束阻塞
    e.set()

    清除对该事件对象的set
    e.clear()

    监测对象是否被设置 设置返回True
    e.is_set()

    锁 Lock

    multiprocessing ----》 Lock

    lock = Lock()

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

    with lock: ---》 给with代码段上锁
    ....
    ....

    -----------------> with 代码段结束自动解锁

    * 在lock对象处于上锁状态的时候,再企图上锁则会阻塞
    直到锁被释放,才能继续执行上锁操作


    线程

    * 线程也是所任务编程的一种方法,可以使用计算机多核资源。是计算机核心分配的最小单位
    * 线程又称为轻量级的进程,在创建和删除时消耗的计算机资源小

    线程和进程关系
    * 一个进程中可以包含多个线程
    * 进程中的所有线程共享进程的空间资源 (空间,全局变量,分配的内存等)
    * 线程也有自己的特有属性,比如 指令集 TID等

    创建线程
    import threading

    threading.Tread

    Thread()
    功能 : 创建线程
    参数 : target 线程函数
    args 元组 给线程函数位置传参
    kwargs 字典 给线程函数字典传参
    name 给线程取名字 (默认Thread-1)
    返回 : 线程对象

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

    t.is_alive() 查看线程状态
    t.name 查看线程名称
    threading.currentThread() 得到线程对象
    t.setName() 设置线程名称

    t.daemon 属性
    默认 为False 主线程执行完毕不会影响分支线程的执行
    如果设置为True 则主线执行完毕其他线程也会终止

    t.isDaemon() : 判断 daemon属性是True or False

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


    线程的通信

    通过全局变量进行通信

    进程和线程的区别和联系
    1. 两者都是多任务编程方式,均可使用计算机的多核
    2. 进程的创建要比线程消耗更多的资源
    3. 进程空间独立,数据安全性更好操作,有专门的进程间通信方式
    4. 线程使用全局变量通信,往往要和同步互斥机制配合防止产生资源的争夺
    5.一个进程可以包含多个线程,线程共享进程资源。
    6. 进程线程都有自己的特有资源。

    使用场景 :
    需要创建较多的并发,任务比较简单,线程比较合适。
    如果程序见数据资源使用重叠比较多,要考虑到线程锁是否需要更复杂的逻辑
    如果多个任务并无什么关联性,不易用多线程将其融入到一个进程中
    python线程不适用于计算密集型并发


    创建自定义线程类 :

    1.继承Thread类
    2.重写 run 方法


    线程中同步互斥方法
    Event 线程事件
    e = Event()
    e.wait() e.set() e.clear()

    Lock 线程锁
    lock = Lock() 创建锁
    lock.acquire() 加锁
    lock.release() 解锁

    作业 :
    信号通信
    司机和售票员的故事
    1. 创建父子进程,分别表示司机和售票员
    2. 当售票员捕捉到 SIGINT信号时 给司机发送 SIGUSER1信号, 此时司机打印 “老司机开车了”
    当售票员捕捉到 SIGQUIT时 给司机发送 SIGUSER2信号,此时司机打印“系好安全带,车速有点快”
    当司机捕捉到 SIGTSTP时,发送SIGUSER1给售票员,售票员打印 “到站了,请下车”
    3. 到站后 售票员先下车(子进程退出),然后司机下车

    温馨提示 : 键盘发送信号会给终端所有进程


    TFTP文件服务器

    文件的上传,下载,和服务端文件库的查看

    服务端 客户端
    1.查看文件库中有哪些文件
    2.下载文件到本地
    3.将本地的文件上传到文件库

    ***************************************************************
    from multiprocessing import Event

    #创建事件对象
    e = Event()

    print(e.is_set())

    e.set()

    e.wait()

    print(e.is_set())

    #将设置清除 wait又阻塞
    e.clear()

    e.wait()

    ****************************************************************
    from threading import Thread
    from time import ctime,sleep

    #编写自己的线程类
    class MyThread(Thread):
    def __init__(self,func,args,name = "Tedu"):
    super().__init__()
    self.func = func
    self.args = args
    self.name = name

    # 调用start会自动运行
    def run(self):
    self.func(*self.args)

    def player(file,sec):
    for i in range(2):
    print("playing %s : %s"%(file,ctime()))
    sleep(sec)


    t = MyThread(player,('baby.mp3',3))
    t.start()
    t.join()

    ******************************************************************
    from multiprocessing import Event,Process
    from time import sleep

    def wait_event():
    print("process1也想操作临界区,但是要阻塞等待主进程")
    e.wait()
    print("主进程操作完了,轮到我了",e.is_set())

    def wait_event_timeout():
    print("process2也想操作临界区,但是要阻塞等待主进程")
    e.wait(2)
    print("我等不了了,还是执行别的吧",e.is_set())


    e = Event()

    p1 = Process(name = 'block',target = wait_event)
    p2 = Process(name = 'non-block',
    target = wait_event_timeout)

    p1.start()
    p2.start()

    print("假设正在忙碌的操作临界资源")
    sleep(3)
    e.set()
    print("主进程操作完了,开放临界区")

    p1.join()
    p2.join()

    **************************************************************
    from multiprocessing import Process,Lock
    import sys
    from time import sleep

    #sys.stdout为所有进程的共有资源
    def worker1():
    lock.acquire() #上锁
    for i in range(5):
    sleep(1)
    sys.stdout.write("worker1 输出 ")
    lock.release() #解锁

    def worker2():
    #with方式上锁
    with lock:
    for i in range(5):
    sleep(1)
    sys.stdout.write("worker2 输出 ")

    #创建Lock对象
    lock = Lock()

    w1 = Process(target = worker1)
    w2 = Process(target = worker2)

    w1.start()
    w2.start()

    w1.join()
    w2.join()

    **************************************************************
    from multiprocessing import
    Semaphore,Process,current_process
    from time import sleep

    #创建信号量初始值为3
    sem = Semaphore(3)

    def fun():
    print("进程 %s 等待信号量"%current_process())
    #第四个进程无信号资源会阻塞
    sem.acquire()
    print("进程 %s 消耗信号量"%current_process())
    sleep(3)
    print("进程 %s 添加信号量"%current_process())
    sem.release()

    jobs = []
    for i in range(4):
    p = Process(target = fun)
    p.start()
    jobs.append(p)

    for i in jobs:
    i.join()

    **************************************************************
    import signal
    from time import sleep

    signal.alarm(5)

    #采用默认的方法处理SIGALRM信号
    # signal.signal(signal.SIGALRM,signal.SIG_DFL)

    #忽略信号
    signal.signal(signal.SIGALRM,signal.SIG_IGN)
    signal.signal(signal.SIGINT,signal.SIG_IGN)

    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(7)

    #通过自定义方法处理
    signal(SIGALRM,handler)
    signal(SIGINT,handler)

    while True:
    print("waiting for a signal")
    time.sleep(2)

    **************************************************************
    import threading
    from time import sleep

    #线程函数
    def music():
    while True:
    sleep(2)
    print("播放葫芦娃")

    #创建线程和函数music关联
    t = threading.Thread(target = music)
    #启动线程
    t.start()

    while True:
    sleep(1.5)
    print("想听灌篮高手")

    #等待回收线程
    t.join()
    print("+++++++++++++++++++")

    **************************************************************
    #线程对象属性
    from threading import Thread,currentThread
    from time import sleep

    def fun(sec):
    print("线程属性测试")
    sleep(sec)
    print(" %s 线程结束"%currentThread().getName())

    thread = []
    for i in range(3):
    t = Thread(name = "tedu" + str(i),
    target = fun,args = (3,))
    t.start()
    thread.append(t)

    for i in thread:
    i.join()
    print("thread name:",i.name)
    print("alive:",i.is_alive())

    **************************************************************
    #daemon属性
    from threading import Thread
    from time import sleep

    def fun():
    print("Daemon 属性测试")
    sleep(5)
    print("线程结束")

    t = Thread(target = fun)

    #为线程设置名字
    t.setName("tedu")

    #daemon属性设置为True
    #t.daemon = True
    t.setDaemon(True)
    print(t.isDaemon())

    t.start()
    t.join(2)
    print("=====主线程结束======")

    **************************************************************
    import threading
    from time import sleep

    s = None

    #创建线程事件对象
    e = threading.Event()

    def bar():
    print("呼叫foo")
    global s
    s = "天王盖地虎"

    def foo():
    print("等待口令")
    sleep(2)
    if s == "天王盖地虎":
    print("foo收到:",s)
    else:
    print("打死他")
    e.set()

    def fun():
    print("呵呵...")
    sleep(1)
    e.wait()
    global s
    s = "小鸡炖蘑菇"


    t1 = threading.Thread(name = 'bar',target = bar)
    t2 = threading.Thread(name = 'foo',target = foo)
    t3 = threading.Thread(name = 'fun',target = fun)
    t1.start()
    t2.start()
    t3.start()
    t1.join()
    t2.join()
    t3.join()

    **************************************************************
    from threading import Thread
    from time import sleep

    #通过全局变量进行线程通信
    a = 1

    def foo():
    global a
    a = 1000

    def bar():
    sleep(1)
    print("a =",a) # a = 1000

    t1 = Thread(target = foo)
    t2 = Thread(target = bar)

    t1.start()
    t2.start()

    t1.join()
    t2.join()

    **************************************************************
    import threading

    a = b = 0

    lock = threading.Lock()

    def value():
    while True:
    lock.acquire()
    if a != b:
    print("a = %d,b = %d"%(a,b))
    lock.release()

    t = threading.Thread(target = value)
    t.start()

    while True:
    lock.acquire()
    a += 1
    b += 1
    lock.release()

    t.join()
  • 相关阅读:
    【zZ】OpenCV HOGDescriptor 参数图解
    [C]遍历目录下所有文件
    drawing
    转:基于用户投票的排名算法系列
    编码格式
    泛型
    接口
    隐藏方法不能实现多态性
    结构
    静态
  • 原文地址:https://www.cnblogs.com/wcin/p/9119117.html
Copyright © 2020-2023  润新知