PythonThread_07_bj

前情回顾
进程对象 p 属性
p.name 进程名称
p.pid 进程PID
p.daemon 父进程的退出影响子进程

自定义进程类 继承Process 重写run

进程池 大量的事件需要频繁创建删除进程的情况
Pool() 创建进程池对象
apply_async() 添加事件
close() 关闭进程池
join() 回收进程池

进程间通信:管道 消息队列 共享内存 信号 信号量 套接字

管道 : Pipe —》 fd1 fd2
消息队列:Queue —》q
q.put() q.get() q.qsize() q.full()
q.empty() q.close()
共享内存: Value obj.value
Arrary shm[]


信号

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

kill -l 查看信号
kill -signame PID 给PID的进程发送一个信号

关于信号

信号名称 : 系统定义, 名字或者数字
信号含义 : 系统定义, 信号的作用
默认处理方法:当一个进程接收到信号时默认产生的效果
终止进程 暂停进程 忽略
e.g.
SIGHUP 连接断开
SIGINT CTRL + C
SIGQUIT CTRL +
SIGTSTP CTRL + Z
SIGKILL 终止进程且不能被处理
SIGSTOP 暂停进程且不能被处理
SIGALRM 时钟信号
SIGCHLD 子进程状态改变给父进程发送

Python进行信号处理

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

#01_kill.py

import os
import signal

#给7264进程发送SIGKILL信号
os.kill(7264,signal.SIGKILL)

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

  • 在一个进程中只允许有一个时钟,设置第二个的时候时间就会重置

程序执行的异步和同步

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

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

#02_alarm.py

import signal
import time

#3秒后向自身发送SIGALRM信号
signal.alarm(3)
time.sleep(2)
signal.alarm(5)

#阻塞等待一个信号的到来
signal.pause()

while True:
time.sleep(1)
print(“等待时钟信号…”)

signal.pause()
功能 : 阻塞等待进程收到一个信号

signal.signal(signum,handler)
功能 : 处理信号
参数 : signum : 要处理的信号
handler : 信号的处理方法
可选值 : SIG_DFL 表示使用默认方法处理
SIG_IGN 表示忽略这个信号
func 自定义函数

				自定义函数格式: def func(sig,frame)
				                 sig:接收到的信号
								 frame:信号结构对象
  • signal函数是一个异步处理函数
  • signal函数不能处理SIGKILL,SIGSTOP信号
  • 在父进程中加上signal(SIGCHLD,SIG_IGN),当子进程退
    出时会自动交由系统处理

#03_signal0.py
import signal
from time import sleep

signal.alarm(5)

#使用默认的方法处理SIGALRM信号

signal.signal(signal.SIGALRM,signal.SIG_DFL)

#使用忽略的方法处理SIGALRM信号
signal.signal(signal.SIGALRM,signal.SIG_IGN)
#忽略ctrl+c
signal.signal(signal.SIGINT,signal.SIG_IGN)

while True:
sleep(2)
print(“让你恩ctrl + c”)
print(“等待时钟…”)

#04_signal1.py
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() 将信号量数量减一 信号量为0会阻塞
sem.release() 将信号量数量加一
sem.get_value() 获取当前信号量的值

#05_sem.py
from multiprocessing import Semaphore,Process
from time import sleep
import os

#创建信号量 初始 3
sem = Semaphore(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.start()

for i in jobs:
i.join()

print(sem.get_value())

进程 4650 等待信号量

进程 4651 等待信号量

进程 4651 消耗信号量

进程 4650 消耗信号量

进程 4652 等待信号量

进程 4652 消耗信号量

进程 4653 等待信号量

进程 4651 添加信号量

进程 4653 消耗信号量

进程 4650 添加信号量

进程 4652 添加信号量

进程 4653 添加信号量

3

同步互斥机制

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

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

同步 : 同步是一种合作关系,为完成某个任务多进程
或者多线程之间形成一种协调,按照约定或条
件一次执行操作临界资源,相互告知资源使用
情况。

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

Event 事件

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

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

事件设置 e处于设置状态,e.wait()不再阻塞
e.set()

事件清除 e处于未设置状态,e.wait()阻塞
e.clear()

事件判断 判断e的当前状态
e.is_set()

#06_event_test.py
from multiprocessing import Event

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

print(e.is_set())

e.set() #设置事件

e.wait(5)
print("==================")
print(e.is_set())

e.clear() #清除设置
e.wait()

07_process_event.py

from multiprocessing import Process,Event
from time import sleep

def wait_event():
print(“想操作临界区但是要等待事件设置”)
e.wait()
print(“终于轮到我操作临界区了”,e.is_set())

def wait_event_timeout():
print(“也想操作临界区但是也要等2秒吧”)
e.wait(2)
print(“2秒到了我不等了”,e.is_set())

e = Event()
p1 = Process(target = wait_event)
p2 = Process(target = wait_event_timeout)

p1.start()
p2.start()

print(“假装主进程在操作临界资源”)
sleep(3)
e.set()
print(“开放临界资源”)

p1.join()
p2.join()

想操作临界区但是要等待事件设置

也想操作临界区但是也要等2秒吧

假装主进程在操作临界资源

2秒到了我不等了 False

开放临界资源

终于轮到我操作临界区了 True


锁 Lock

multiprocessing —》 Lock

创建对象
lock = Lock()

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

上锁状态 : 此时执行acquire()操作会阻塞
解锁状态 : 执行acquire()操作为非阻塞

with lock: ----》 上锁


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

#08_process_lock.py
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() #解锁

def writer2():
#with方式上锁
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()

线程

什么是线程

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

线程的特征

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

threading 模块创建线程

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

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

#09_thread1.py
import threading
from time import sleep
import os

a = 1

#线程函数
def music():
global a
a = 1000
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)

想听灌篮高手 5356

播放葫芦娃 5356

想听灌篮高手 5356

播放葫芦娃 5356

想听灌篮高手 5356

想听灌篮高手 5356

播放葫芦娃 5356

想听灌篮高手 5356

播放葫芦娃 5356

播放葫芦娃 5356

a = 1000


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

#10_thread2.py
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(name = ‘tedu’ + str(i),
target = fun,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()

线程属性测试

True

线程属性测试

True

线程属性测试

True

tedu2

tedu0 线程结束

Tarena 线程结束

tedu2 线程结束


t.daemon 属性

默认情况下主线程的结束不会影响到分支线程的执行
如果设置为True 则主线程退出分支线程也会退出

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

判断daemon属性:
t.isDaemon()

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

#11_thread3.py
#daemon属性
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(“主线程结束”)

True

主线程结束

创建自己的线程类

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

#12_myThread.py
from threading import Thread
from time import ctime,sleep

#自己的线程类
class MyThread(Thread):
def init(self,target,
name = “Tedu”,args = (),kwargs = {}):
#运行Thread类中的__init__方法以获取父类原有属性
super().init()
self.name = name
self.target = target
self.args = args
self.kwargs = kwargs

def run(self):
    self.target(*self.args)

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

#playing 葫芦娃 : Tue Aug 7 15:02:25 2018
#playing 葫芦娃 : Tue Aug 7 15:02:28 2018

作业 :

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

#driver.py
import multiprocessing as mp
from signal import *
import sys,os
import time

def driver_handle(sig,frame):
if sig == SIGUSR1:
print(“老司机开车了”)
elif sig == SIGUSR2:
print(“车速有点快,系好安全带”)
elif sig == SIGTSTP:
os.kill(p.pid,SIGUSR1)

def saler_handle(sig,frame):
if sig == SIGINT:
os.kill(os.getppid(),SIGUSR1)
elif sig == SIGQUIT:
os.kill(os.getppid(),SIGUSR2)
elif sig == SIGUSR1:
print(“到站了,请下车”)
sys.exit(“售票员下车”)

def saler():
signal(SIGINT,saler_handle)
signal(SIGQUIT,saler_handle)
signal(SIGUSR1,saler_handle)
signal(SIGTSTP,SIG_IGN)
while True:
time.sleep(3)
print(“Python带你去远方”)

p = mp.Process(target = saler)
p.start()

signal(SIGUSR1,driver_handle)
signal(SIGUSR2,driver_handle)
signal(SIGTSTP,driver_handle)
signal(SIGINT,SIG_IGN)
signal(SIGQUIT,SIG_IGN)

p.join()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值