Concurrent programming (process articles, to be continued)

One, socketserver module

  • This module is used to achieve concurrent effects in network programming
  • The following simulates the concurrent effect of a customer inputting information and the server returning the information in uppercase

1. Server

import socketserver

#基于tcp协议
'''
self.request=>conn
'''
class MyRequestHandle(socketserver.BaseRequestHandler):
    def handle(self):
    	print(self.client_address)
        while True:
            try:
                msg = self.requset.recv(1024)
                if len(msg) == 0: break
                self.request.send(msg.upper())
            except Exception:
                break
        self.request.close()

#服务端应该做两件事情
#第一件事:循环地从半链接池中取出链接 请求与其建立双向链接
#第二件事:拿到链接对象,与其进行通信循环

s=socketserver.TCPServer(('127.0.0.1',8880),MyRequestHandle)
s.serve_forever()

2. Client 1

import socket


client = socket(AF_INET,SOCK_STREAM)
cliene.connect(('127.0.0.1',8880))

while True:
    msg = input('请输入命令:').strip()
    if len(msg) == 0: continue
    client.send(msg.encode('utf-8'))
    
    res = client.rece(1024)
    print(res.decode('utf-8'))

3. Client 2

import socket


client = socket(AF_INET,SOCK_STREAM)
cliene.connect(('127.0.0.1',8880))

while True:
    msg = input('请输入命令:').strip()
    if len(msg) == 0: continue
    client.send(msg.encode('utf-8'))
    
    res = client.rece(1024)
    print(res.decode('utf-8'))

4. Effect screenshot

Insert picture description here
Insert picture description here
Insert picture description here

2. Some important knowledge

  • The development history of the operating system revolves around improving the efficiency of the CPU
  • Process: the running program
  • code
  • Multi-channel technology:
    • Purpose: Single-core concurrency
    • Mainly to realize the space reuse and time reuse of the program to the computer
    • Spatial reuse: multiple programs share a computer hardware system
    • Time reuse: save the running state of the program + switch the program
      + switch is divided into two situations:
      1. The program encounters an IO operation
      2. The program runs too long
  • Parallel and concurrency
    • Concurrency: looks like doing different things at the same time
    • Parallel: doing different things at the same time
  • Process scheduling
    • First come first serve scheduling algorithm
    • Short job priority scheduling algorithm
    • Time slice rotation method + multi-level feedback queue
  • Process three states
    + ready state, running state, blocking state
    + the program must go through the ready state before entering the running state
    + the blocking state is to enter the blocking state when encountering IO and other operations
  • Synchronous & asynchronous, blocking & non-blocking
    • Synchronous and asynchronous is for task submission
    • Blocking non-blocking is for the running state of the program
    • The most efficient is asynchronous non-blocking

Three, two ways to create a process and join method

1. Start the process in non-program

Just double-click several applications, if several applications are running at the same time, multiple processes will be opened

2. Start the process at the program level

There are two ways to create a process. The
first one has many applications

3.join method

  • Simply put, let the main process wait for the child process to run, and then the main program will run down
  • Let's make a small program for program time test
from multiprocessing import Process
import time

def task(i):
    time.sleep(i)

if __name__ == '__main__':
    pro_lis = []
    start = time.time()
    # 创建三个进程
    for i in range(3):
        p = Process(target=task,args=(i,))
        pro_lis.append(p)

    # 启动三个进程
    for pro in pro_lis:
        pro.start()
    print(time.time()-start)

Running result: 0.0258924961090087

Although this is not the final running time of the program, in fact, the time should be more than 2s, but combined with the following example, you can see the usage of join, which is a bit concurrency and serial.

from multiprocessing import Process
import time

def task(i):
    time.sleep(i)

if __name__ == '__main__':
    pro_lis = []
    start = time.time()
    # 创建三个进程
    for i in range(3):
        p = Process(target=task,args=(i,))
        pro_lis.append(p)
    
    # 启动三个进程
    for pro in pro_lis:
        pro.start()
        pro.join()
    print(time.time()-start)

Result: 4.735849142074585

Fourth, data isolation between processes

  • This is a conclusion, let’s verify
from multiprocessing import Process


money = 100


def task():
    global money  # 局部修改全局
    money = 666
    print('子',money)


if __name__ == '__main__':
    p = Process(target=task)
    p.start()
    p.join()
    print(money)

Result:

666
100

Five, process objects and other methods

  • p.terminate() # kill the current process
  • p.is_alive() # Determine whether the current process is alive
  • os.getpid() to get the process number is equivalent to current_process().pid
    • Supplement: Windows: view all processes in tasklist in cmd
    • tasklist | find "keywords" can filter the results, that is, get the process of a certain program separately
      +os.getppid() #get the parent process number
from multiprocessing import Process, current_process
import time
import os


def task():
    print('%s is running'%current_process().pid)  # 查看当前进程的进程号
    print('%s is running'%os.getpid())  # 查看当前进程的进程号
    print('子进程的主进程号%s'%os.getppid())  # 查看当前进程的进程号
    time.sleep(30)


if __name__ == '__main__':
    p = Process(target=task)
    p.start()
    p.terminate()  # 杀死当前进程
    # 是告诉操作系统帮你去杀死当前进程 但是需要一定的时间 而代码的运行速度极快
    time.sleep(0.1)
    print(p.is_alive())  # 判断当前进程是否存活
    """
    一般情况下我们会默认将
    存储布尔值的变量名
    和返回的结果是布尔值的方法名
    都起成以is_开头
    """
    print('主')
    print('主',current_process().pid)
    print('主',os.getpid())
    print('主主',os.getppid())  # 获取父进程的pid号





result:

False
主
主 92569256
主主 18360

Six, zombie process, orphan process, daemon process

  • The zombie process refers to the process that does not die after the end, and it will be kept for a period of time for the parent process to view the process number, running time and other information of the process. When the parent process exists and has been spawning child processes, it opens up unlimited memory space. this is not good

  • The orphan process is the survival of the child process, while the parent process dies, the operating system has a mechanism to solve the problem of orphan process recycling

  • A daemon thread is a process that lives and dies with the operating system

  • p.daemon = True # Set process p as a daemon process

  • This sentence must be placed above the start method to be effective, otherwise an error will be reported directly

An example: the ancient emperor died and the eunuchs around him must also gameover

from multiprocessing import Process
import time


def task(name):
    print('%s总管正在活着'% name)
    time.sleep(3)
    print('%s总管正在死亡' % name)


if __name__ == '__main__':
    p = Process(target=task,args=('太监',))
    # p = Process(target=task,kwargs={'name':'egon'})
    p.daemon = True  # 将进程p设置成守护进程  这一句一定要放在start方法上面才有效否则会直接报错
    p.start()
    print('皇帝寿终正寝')

Result: Pay attention to the eunuch. .

皇帝寿终正寝

After commenting the daemon

from multiprocessing import Process
import time


def task(name):
    print('%s总管正在活着'% name)
    time.sleep(3)
    print('%s总管正在死亡' % name)


if __name__ == '__main__':
    p = Process(target=task,args=('太监',))
    # p = Process(target=task,kwargs={'name':'egon'})
    # p.daemon = True  # 将进程p设置成守护进程  这一句一定要放在start方法上面才有效否则会直接报错
    p.start()
    print('皇帝寿终正寝')

result:

皇帝寿终正寝
太监总管正在活着
太监总管正在死亡

Seven, mutual exclusion lock

Eight, queue & message queue, IPC mechanism

Nine, producer consumer model

Guess you like

Origin blog.csdn.net/qq_49821869/article/details/112910543