博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python网络编程(进程通信、信号、线程锁、多线程)
阅读量:6158 次
发布时间:2019-06-21

本文共 5314 字,大约阅读时间需要 17 分钟。

什么是进程通讯的信号?
用过Windows的我们都知道,当我们无法正常结束一个程序时,
可以用任务管理器强制结束这个进程,但这其实是怎么实现的呢?
同样的功能在Linux上是通过生成信号和捕获信号来实现的,
运行中的进程捕获到这个信号然后作出一定的操作并最终被终止。
信号是UNIX和Linux系统响应某些条件而产生的一个事件,
接收到该信号的进程会相应地采取一些行动。通常信号是由一个错误产生的。
但它们还可以作为进程间通信或修改行为的一种方式,
明确地由一个进程发送给另一个进程。一个信号的产生叫生成,接收到一个信号叫捕获
什么是线程锁?
       
1.在单一进程的情况下可以叫单进程也可以叫单线程
         2.
线程锁的大致思想是:如果线程A和线程B会执行实例的两个函数a和b
如果A必须在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 + Cwhile 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 sleepdef 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()  # 子进程setprint("主进程操作完毕")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输出\n")    lock.release() #解锁# 虽然都sleep1秒但是 若不加锁会每1秒打印两次# 由于上锁原因 w1执行完临界区w2才能被执行 一秒一次def writer2():    with lock:        for i in range(5):            sleep(1)            sys.stdout.write("writer2输出\n")#创建锁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类继承Threadclass 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()

转载地址:http://easfa.baihongyu.com/

你可能感兴趣的文章
都市求生日记第一篇
查看>>
Java集合---HashMap源码剖析
查看>>
SQL优化技巧
查看>>
thead 固定,tbody 超出滚动(附带改变滚动条样式)
查看>>
Dijkstra算法
查看>>
css 动画 和 响应式布局和兼容性
查看>>
csrf 跨站请求伪造相关以及django的中间件
查看>>
MySQL数据类型--与MySQL零距离接触2-11MySQL自动编号
查看>>
生日小助手源码运行的步骤
查看>>
Configuration python CGI in XAMPP in win-7
查看>>
bzoj 5006(洛谷 4547) [THUWC2017]Bipartite 随机二分图——期望DP
查看>>
CF 888E Maximum Subsequence——折半搜索
查看>>
欧几里德算法(辗转相除法)
查看>>
面试题1-----SVM和LR的异同
查看>>
MFC控件的SubclassDlgItem
查看>>
如何避免历史回退到登录页面
查看>>
《图解HTTP》1~53Page Web网络基础 HTTP协议 HTTP报文内的HTTP信息
查看>>
unix环境高级编程-高级IO(2)
查看>>
树莓派是如何免疫 Meltdown 和 Spectre 漏洞的
查看>>
雅虎瓦片地图切片问题
查看>>