python中启动子进程
并发编程
并发 :多段程序看起来是同时运行的
ftp 网盘
不支持并发
socketserver 多进程 并发
异步
  两个进程 分别做不同的事情

创建新进程
join :阻塞 直到 子进程结束
守护进程 daemon :子(守护)进程随着主进程代码的结束而结束
进程之间数据隔离
使用类来开启一个进程 :自定义类 继承Process 重写run方法 传参数需要重写init
属性 pid name
方法 terminate is_alive

 

作业讲解:

socket聊天并发实例,使用原生socket的TCP协议,实现一个聊天的并发实例

先来一个简单的,单线程

server.py

import socket
sk = socket.socket()
sk.bind(('127.0.0.1',9000))
sk.listen()
conn,addr = sk.accept()
msg = conn.recv(1024).decode('utf-8')
conn.send((msg+'sb').encode('utf-8'))
print(msg)
conn.close()

client.py

import socket
sk = socket.socket()
sk.connect(('127.0.0.1',9000))
inp = input('>>>').encode('utf-8')
sk.send(inp)
msg = sk.recv(1024).decode('utf-8')
print(msg)
sk.close()

先执行server.py,再执行client.py

输出:

>>>111
111sb

 

如果要多次会话呢?加一个while循环

server.py

import socket
sk = socket.socket()
sk.bind(('127.0.0.1',9000))
sk.listen()
conn,addr = sk.accept()
while True:
    msg = conn.recv(1024).decode('utf-8')
    conn.send((msg+'sb').encode('utf-8'))
    print(msg)
conn.close()
sk.close()

client.py

import socket
sk = socket.socket()
sk.connect(('127.0.0.1',9000))
while True:
    inp = input('>>>').encode('utf-8')
    sk.send(inp)
    msg = sk.recv(1024).decode('utf-8')
    print(msg)
sk.close()

但是这样,只能一个客户端和服务器连接,再来一个客户端,就卡住了。

sk.accept()是阻塞的,那么,如何改成异步呢?

将server里面的recv和send放到一个函数里面,使用多线程调用

server.py

import socket
from multiprocessing import Process
def chat(conn):  # 聊天
    while True:
        msg = conn.recv(1024).decode('utf-8')
        print(msg)
        conn.send((msg + '_sb').encode('utf-8'))
    conn.close()

if __name__ == '__main__':
    sk = socket.socket()
    sk.bind(('127.0.0.1',9000))
    sk.listen()
    while True:
        conn,addr = sk.accept()
        Process(target=chat,args=[conn,]).start()   # 异步
    sk.close()

先执行server.py,再执行client.py

多开几个客户端,也没问题

python 全栈开发,Day39(进程同步控制(锁,信号量,事件),进程间通信(队列,生产者消费者模型))

这就有点像接线员一样,接到客户打的电话,转给相应的人处理
这样,就有多个子进程,同时执行,实现多个客户端同时连接

 

进程同步(multiprocess.Lock、Semaphore、Event) 

锁 —— multiprocess.Lock

      通过刚刚的学习,我们千方百计实现了程序的异步,让多个任务可以同时在几个进程中并发处理,他们之间的运行没有顺序,一旦开启也不受我们控制。尽管并发编程让我们能更加充分的利用IO资源,但是也给我们带来了新的问题。

  当多个进程使用同一份数据资源的时候,就会引发数据安全或顺序混乱问题。

 

多进程抢占输出资源

import os
import time
import random
from multiprocessing import Process

def work(n):
    print('%s: %s is running' %(n,os.getpid()))
    time.sleep(random.random())
    print('%s:%s is done' %(n,os.getpid()))

if __name__ == '__main__':
    for i in range(3):
        p=Process(target=work,args=(i,))
        p.start()

执行输出:

1: 16548 is running
0: 1448 is running
2: 1096 is running
2:1096 is done
0:1448 is done
1:16548 is done

看输出结果,都是乱的。
如果想有序的执行,先run,再done,怎么办?
需要用到锁

import os
import time
import random
from multiprocessing import Lock
from multiprocessing import Process

def work(n,lock):
    lock.acquire()  #取得锁
    print('%s: %s is running' %(n,os.getpid()))
    time.sleep(random.random())
    print('%s:%s is done' %(n,os.getpid()))
    lock.release()  #释放锁

if __name__ == '__main__':
    lock = Lock()  #创建锁
    for i in range(5):
        p=Process(target=work,args=(i,lock))
        p.start()

执行输出:

0: 17468 is running
0:17468 is done
2: 16688 is running
2:16688 is done
1: 15984 is running
1:15984 is done
3: 15828 is running
3:15828 is done
4: 18156 is running
4:18156 is done

 从结果上来看,结果就比较整齐了。先run,再done。结果是无序的

#创建锁
mutex = threading.Lock()
#锁定
mutex.acquire([timeout])#timeout是超时时间
#释放
mutex.release()

其中,锁定方法acquire可以有一个超时时间的可选参数timeout。如果设定了timeout,则在超时后通过返回值可以判断是否得到了锁,从而可以进行一些其他的处理。
acquire参数

相关文章:

  • 2021-05-15
  • 2022-12-23
  • 2021-12-05
  • 2021-11-29
  • 2022-12-23
  • 2021-12-18
  • 2022-12-23
  • 2021-05-20
猜你喜欢
  • 2022-12-23
  • 2021-09-06
  • 2021-05-19
  • 2022-02-13
  • 2021-11-05
  • 2021-04-23
  • 2022-01-21
相关资源
相似解决方案