Python网络编程(进程通信、信号、线程锁、多线程)

简介: 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输出\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类继承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()




相关文章
|
11月前
|
设计模式 消息中间件 安全
【JUC】(3)常见的设计模式概念分析与多把锁使用场景!!理解线程状态转换条件!带你深入JUC!!文章全程笔记干货!!
JUC专栏第三篇,带你继续深入JUC! 本篇文章涵盖内容:保护性暂停、生产者与消费者、Park&unPark、线程转换条件、多把锁情况分析、可重入锁、顺序控制 笔记共享!!文章全程干货!
535 1
|
11月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
587 1
|
11月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
513 1
|
监控 编译器 Python
如何利用Python杀进程并保持驻留后台检测
本教程介绍如何使用Python编写进程监控与杀进程脚本,结合psutil库实现后台驻留、定时检测并强制终止指定进程。内容涵盖基础杀进程、多进程处理、自动退出机制、管理员权限启动及图形界面设计,并提供将脚本打包为exe的方法,适用于需持续清理顽固进程的场景。
|
并行计算 安全 Java
Python GIL(全局解释器锁)机制对多线程性能影响的深度分析
在Python开发中,GIL(全局解释器锁)一直备受关注。本文基于CPython解释器,探讨GIL的技术本质及其对程序性能的影响。GIL确保同一时刻只有一个线程执行代码,以保护内存管理的安全性,但也限制了多线程并行计算的效率。文章分析了GIL的必要性、局限性,并介绍了多进程、异步编程等替代方案。尽管Python 3.13计划移除GIL,但该特性至少要到2028年才会默认禁用,因此理解GIL仍至关重要。
1448 16
Python GIL(全局解释器锁)机制对多线程性能影响的深度分析
|
数据采集 Java 数据处理
Python实用技巧:轻松驾驭多线程与多进程,加速任务执行
在Python编程中,多线程和多进程是提升程序效率的关键工具。多线程适用于I/O密集型任务,如文件读写、网络请求;多进程则适合CPU密集型任务,如科学计算、图像处理。本文详细介绍这两种并发编程方式的基本用法及应用场景,并通过实例代码展示如何使用threading、multiprocessing模块及线程池、进程池来优化程序性能。结合实际案例,帮助读者掌握并发编程技巧,提高程序执行速度和资源利用率。
896 0
|
供应链 安全 NoSQL
PHP 互斥锁:如何确保代码的线程安全?
在多线程和高并发环境中,确保代码段互斥执行至关重要。本文介绍了 PHP 互斥锁库 `wise-locksmith`,它提供多种锁机制(如文件锁、分布式锁等),有效解决线程安全问题,特别适用于电商平台库存管理等场景。通过 Composer 安装后,开发者可以利用该库确保在高并发下数据的一致性和安全性。
379 6
|
Java 关系型数据库 MySQL
【JavaEE“多线程进阶”】——各种“锁”大总结
乐/悲观锁,轻/重量级锁,自旋锁,挂起等待锁,普通互斥锁,读写锁,公不公平锁,可不可重入锁,synchronized加锁三阶段过程,锁消除,锁粗化
|
监控 JavaScript 前端开发
python中的线程和进程(一文带你了解)
欢迎来到瑞雨溪的博客,这里是一位热爱JavaScript和Vue的大一学生分享技术心得的地方。如果你从我的文章中有所收获,欢迎关注我,我将持续更新更多优质内容,你的支持是我前进的动力!🎉🎉🎉
338 0
|
Linux 数据库 Perl
【YashanDB 知识库】如何避免 yasdb 进程被 Linux OOM Killer 杀掉
本文来自YashanDB官网,探讨Linux系统中OOM Killer对数据库服务器的影响及解决方法。当内存接近耗尽时,OOM Killer会杀死占用最多内存的进程,这可能导致数据库主进程被误杀。为避免此问题,可采取两种方法:一是在OS层面关闭OOM Killer,通过修改`/etc/sysctl.conf`文件并重启生效;二是豁免数据库进程,由数据库实例用户借助`sudo`权限调整`oom_score_adj`值。这些措施有助于保护数据库进程免受系统内存管理机制的影响。

热门文章

最新文章

推荐镜像

更多