人工智能(PythonNet)—— 进程和线程、同步互斥、集成模块(socketserver)

一、进程和线程

1、特征

        a、进程特征
            * 进程是操作系统资源分配的最小单位
            * 每个进程单独占有4G虚拟内存
            * 进程之间相互独立,运行互不影响
        b、线程特征
            * 线程是计算机核心分配的最小单位
            * 一个进程可以包含多个线程
            * 线程也是一个运行过程,也要消耗计算机资源。多个线程共享其进程的资源和空间
            * 线程也拥有自己特有的资源属性,比如指令集,TID等
            * 线程无论创建还是删除还是运行资源消耗都小于进程
            * 多个线程之间并行执行,互不干扰

2、区别和联系

        * 两者都是多任务编程的方式,都能够使用计算机多核资源
        * 进程创建和删除要比线程消耗更多计算机资源
        * 进程空间独立数据安全性好,有专门的通信方法
        * 线程使用全局变量通信,更加简单,但是往往需要同步互斥操作
        * 一个进程可以包含多个线程,线程共享进程资源
        * 进程、线程都有自己的特有属性资源,如命令、id等

3、使用场景

        线程使用场景:
                如果需要创建较多的并发,任务比较简单,线程比较适合
                如果数据操作和功能比较独立,此时使用进程比较合适
                使用线程时需要考虑到同步互斥复杂程度
                python线程要考虑到GIL问题

        池的使用场景:
                线程池应用较少,用的最多的是进程池。

二、同步互斥机制

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

1、基础概念

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

        同步:是一种合作关系,为完成某个任务,多进程或者多线程之间形成一种协调。按照约定依次执行对临界资源的操作,相互告知相互促进。
        互斥:互斥是一种制约关系,当一个进程占有临界资源就会进行加锁的操作,此时其他进程就无法操作该临界资源。知道使用的进程进行解锁操作后才能使用。

2、进程的同步互斥

a、进程的Event事件

        from multiprocessing import Event

        创建事件对象
        e = Event()

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

        事件设置
        e.set()  
        功能 : 当e被set() 后 e.wait()不再阻塞

        事件清除
        e.clear()
        功能 : 当e被clear()后 e.wait()又会阻塞

        事件判断 判断当前事件对象是否被设置
        e.is_set()

b、进程的锁Lock

        from multiprocessing import Lock

        创建对象
        lock = Lock()

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

        上锁状态 : 执行acquire()操作会阻塞
        解锁状态 : 执行acquire()不阻塞

        with  lock: ---> 上锁
             ...
             ...
                                 ----》 with代码段结束即解锁
        * 在lock对象处于上锁状态的时候,再企图上锁则会阻塞,直到锁被释放,才能继续执行上锁操作

3、线程的同步互斥

线程的资源访问,除了可以通过同步互斥机制来确保数据的安全一致性,也可以通过全局变量进行限制。

a、线程的Event事件

        import threading
        e = threading.Event()
        e.wait([timeout])  如果e为设置状态则不阻塞,未设置则阻塞
        e.set()  将e变为设置状态
        e.clear()  将e设置去除

b、线程的锁Lock

        import threading
        lock = threading.Lock()   创建锁
        lock.acquire()   上锁
        lock.release()   解锁
        
        操作原理 : 重复上锁 acquire()会阻塞

c、线程的条件变量Condition  

        import threading
        创建条件变量对象
        con =  threading.Condition()

        con.acquire() : 对资源加锁,加锁后其他位置再加锁则阻塞
        con.release() : 解锁

        con.wait()  : wait函数只能在 加锁的状态下使用。 wait函数会先解锁(release),然后让线程处于等待通知的阻塞状态

        con.notify()  : 发送通知,线程接收到通知后 结束wait阻塞,并且执行 acquire 加锁操作

4、示例

a、进程的Event

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

b、进程的Lock

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 输出\n")
    lock.release() #解锁

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

#创建Lock对象
lock = Lock()

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

w1.start()
w2.start()

w1.join()
w2.join()

c、线程的global

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

d、线程的Event

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("自己人")
    else:
        print("打死他")
    e.set()

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

t1 = threading.Thread(target = bar)
t2 = threading.Thread(target = foo)
t3 = threading.Thread(target = fun)

t1.start()
t2.start()
t3.start()

t1.join()
t2.join()
t3.join()

d、线程的Lock

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

e、线程的Condition

import threading 
import time 
import datetime 

num = 0 

#条件变量
con = threading.Condition()

class Gov(threading.Thread):
    def run(self):
        global num
        con.acquire()
        while True:
            print("开始拉升股市")
            num += 1 
            print("拉升到 %d 个点"%num)
            time.sleep(2)
            if num == 5:
                print('暂时安全!')
                con.notify()
                print("不操作状态")
                con.wait()
        con.release()

class Consumers(threading.Thread):
    def run(self):
        global num 
        con.acquire()
        while True:
            if num > 0:
                print("开始打压股市")
                num -= 1
                print("下降到%d个点"%num)
                time.sleep(2)
                if num == 0:
                    print("天台在哪")
                    con.notify()
                    print("不能在下降了")
                    con.wait()
        con.release()

t1 = Gov()
t2 = Consumers()
t1.start()
t2.start()        

三、socket 服务器的集成模块

        python2  SocketServer
        python3  socketserver

        功能:通过模块的接口完成基于多进程/多线程的tcp/udp的socket并发程序

 

  意思 等同效果
StreamRequestHandler 处理tcp请求  
DatagramRequestHandler 处理udp请求  
     
ForkingMixIn 建立多进程  
ForkingTCPServer 建立多进程tcp server ForkingMixIn + TCPServer
ForkingUDPServer 建立多进程udp server ForkingMixIn + UDPServer
     
ThreadingMixIn 建立多线程  
ThreadingTCPServer 建立多线程tcp server ThreadingMixIn + TCPServer
ThreadingUDPServer 建立多线程udp server ThreadingMixIn + UDPServer
     
TCPServer 建立tcp server  
UDPServer 建立udp server  

1、多进程TCP并发

from socketserver import * 

#多进程tcp并发

#创建指定类型的服务器
# class Server(ForkingMixIn,TCPServer):
class Server(ForkingTCPServer):
    pass 

#处理具体请求
class Handler(StreamRequestHandler):
    def handle(self):
        #self.request 相当于accept 返回的套接字
        print("Connect from",\
            self.request.getpeername())
        while True:
            data = self.request.recv(1024).decode()
            if not data:
                break
            print(data)
            self.request.send(b"Receive your message")

#生成服务器对象
server = Server(('0.0.0.0',9999),Handler)

#启动服务器
server.serve_forever()

2、多进程UDP并发

from socketserver import *

#多进程udp并发

class Server(ForkingUDPServer):
    pass 

class Handler(DatagramRequestHandler):
    def handle(self):
        #接受消息
        while True:
            data = self.rfile.readline().decode()
            if not data:
                break 
            print(data)
            self.wfile.write(b'Receive message')

server = Server(("0.0.0.0",8888),Handler)
server.serve_forever()

四、附录:目录

        人工智能(PythonNet)—— 目录汇总

你可能感兴趣的:(人工智能,PythonNet)