Python Concurrent Programming Association Process

Source: Internet
Author: User

Read Catalogue

    • A primer
    • Introduction of two-way co-process
    • Three Greenlet
    • Four Gevent Introduction
    • Synchronization and asynchronous of five Gevent
    • Application example of six gevent
    • Seven Gevent application Example two
A primer

The topic in this section is to implement concurrency based on a single thread, that is, to implement concurrency with only one main course (obviously the only CPU available), so we need to look back at the nature of Concurrency: toggle + Save State

The CPU is running a task that, in both cases, will be cut off to perform other tasks (switching is controlled by the operating system), in which case the task is blocked, and the task is taking too long to calculate

PS: When introducing the process theory, the three execution states of the process are mentioned, and the thread is the execution unit, so it can also be understood as the three states of the thread

One: The second situation does not improve efficiency, just to allow the CPU to rain equitably, to achieve the seemingly all tasks are "simultaneous" effect, if more than one task is pure calculation, this switch will reduce efficiency. For this we can verify based on yield. Yield itself is a way to save the running state of a task in a single thread, so let's review it briefly:

# 1 yiled can save state, the state of yield is similar to the state of the operating system's save thread, but yield is code-level controlled, more lightweight # 
simply switching will reduce operational efficiency

Two: The first case of the switch. In the case of a task encountered Io, cut to the task two to execute, so that the task can be used to block the time to complete the task two calculation, the increase in efficiency is this.

yield does not meet IO switching

for single-threaded, we inevitably have IO operations in the program, but if we can control multiple tasks in our own program (that is, at the user program level, not at the operating system level), you can switch to another task to calculate when one task encounters io blocking. This ensures that the thread is in the best possible state, that it can be executed at any time by the CPU, and that we can hide our IO operations to the maximum extent possible at the user program level, thus confusing the operating system to see that the thread seems to have been calculating, the IO is relatively small, This allows more CPU execution permissions to be allocated to our threads.

The nature of the process is that in a single thread, the user controls a task by itself when the IO block is switched on to another task to execute, to improve efficiency. To achieve this, we need to find a solution that can meet the following conditions:

# 1. You can control the switch between multiple tasks, save the state of the task before switching, so that you can resume execution based on the paused position when you rerun.  #2. As a 1 supplement: The IO operation can be detected and the switchover occurs in the case of IO operation
Introduction of two-way co-process

Co-process: is a single-threaded concurrency, also known as micro-threading, fiber. English name Coroutine. One sentence describes what a thread is: The process is a lightweight thread of user-state, that is, the process is scheduled by the user program itself. ,

It should be emphasized that:

# 1. Python threads are at the kernel level, that is, scheduled by the operating system control (such as single-threaded encounters IO or too long execution time will be forced to hand over the CPU execution permissions, switch other threads run)#2. Single-wire range opening process, once IO is encountered, The switch is controlled from the application level (not the operating system) to increase efficiency (!!!) Non-IO operation switching is not efficiency-independent)

Compared to the operating system control thread switching, the user in a single-threaded control of the switch process

The advantages are as follows:

# 1. The transition cost of the association is smaller, is program-level switching, the operating system is not fully aware, and thus more lightweight #2. Concurrency can be achieved within a single thread to maximize CPU utilization

Disadvantages are as follows:

# 1. The nature of the process is single-threaded, unable to take advantage of multi-core, can be a program to open more than one process, each process to open multiple threads, each line range open the coprocessor #2. The association refers to a single thread, so once the association is blocked, will block the entire thread

Summary of the characteristics of the process:

    1. Concurrency must be implemented in only one single thread
    2. No lock required to modify shared data
    3. The context stack in the user program that holds multiple control flows
    4. Additional: A co-process encountered IO operation automatically switch to other Io,yield (how to implement detection, Greenlet can not be implemented, the use of the Gevent module (select mechanism))
Three Greenlet

If we had 20 tasks within a single thread, it would be cumbersome to use the yield generator in order to switch between multiple tasks (we need to get the generator initialized once before calling send ...). Very cumbersome), while using the Greenlet module can be very simple to achieve these 20 tasks directly switching

# installing PIP3 Install Greenlet
 fromGreenletImportGreenletdefEat (name):Print('%s Eat 1'%name) G2.switch ('Egon')    Print('%s Eat 2'%name) G2.switch ()defPlay (name):Print('%s Play 1'%name) G1.switch ()Print('%s Play 2'%name) G1=Greenlet (Eat) G2=Greenlet (play) G1.switch ('Egon')#parameters can be passed in at the first switch, and will not be required at any later time

Simple switching (in the absence of an IO or a duplication of memory space) will slow down the execution of the program

View Code

Greenlet just provides a more convenient way to switch than generator, when cutting to a task execution if you encounter Io, then blocking in place, still does not solve the problem of automatically switching to the IO to improve efficiency.

The code for these 20 tasks for single-line thread usually has both a computational and a blocking operation, and we can get stuck in the execution of Task 1 o'clock, using blocking time to perform task 2 .... In this way, the Gevent module is used to improve efficiency.

Four Gevent Introduction
# installing PIP3 Install gevent

Gevent is a third-party library that makes it easy to implement concurrent or asynchronous programming through Gevent, and the main pattern used in Gevent is Greenlet, which is a lightweight coprocessor that accesses Python in the form of a C extension module. Greenlet all run inside the main program operating system process, but they are dispatched in a collaborative manner.

# usage g1=gevent.spawn (func,1,,2,3,x=4,y=5) creates a co-object g1,spawn the first argument in parentheses is the function name, such as Eat, which can be followed by multiple arguments, which can be positional arguments or keyword arguments. Are all passed to the function eat g2=# wait for the end   of the G1 # wait for the G2 to end #  or two-step cooperation step: Gevent.joinall ([g1,g2])g1.value# get func1 return value

Automatically switch tasks when IO blocking is encountered

View Code

The above example Gevent.sleep (2) simulates an IO block that gevent can identify,

and Time.sleep (2) or other blocking, gevent is not directly recognized by the need to use the following line of code, patching, you can identify the

From gevent import Monkey;monkey.patch_all () must be placed in front of the patched person, such as the Time,socket module

Or we simply remember: To use gevent, you need to put the from Gevent import Monkey;monkey.patch_all () to the beginning of the file

 fromGeventImportMonkey;monkey.patch_all ()ImportgeventImport Timedefeat ():Print('Eat food 1') Time.sleep (2)    Print('Eat Food 2')defPlay ():Print('Play 1') Time.sleep (1)    Print('Play 2') G1=Gevent.spawn (Eat) G2=gevent.spawn (Play_phone) Gevent.joinall ([g1,g2])Print('Master')

We can use Threading.current_thread (). GetName () to view each G1 and G2, viewing the result as dummythread-n, which is a dummy thread

Synchronization and asynchronous of five GeventView CodeApplication example of six geventapplication of the process: CrawlerSeven Gevent application Example two

Socket concurrency under single thread via Gevent (from gevent import Monkey;monkey.patch_all () must be placed before the socket module is imported, otherwise gevent will not recognize the blocking of the socket)

 fromGeventImportMonkey;monkey.patch_all () fromSocketImport*Importgevent#If you do not want to use Money.patch_all () to patch, you can use the gevent to bring your own socket#From gevent Import socket#S=socket.socket ()defServer (server_ip,port): s=socket (af_inet,sock_stream) s.setsockopt (sol_socket,so_reuseaddr,1) S.bind ((Server_ip,port)) S.listen (5)     whiletrue:conn,addr=s.accept () gevent.spawn (TALK,CONN,ADDR)defTalk (conn,addr):Try:         whileTrue:res=CONN.RECV (1024)            Print('Client%s:%s msg:%s'% (addr[0],addr[1],res)) Conn.send (Res.upper () )exceptException as E:Print(e)finally: Conn.close ()if __name__=='__main__': Server ('127.0.0.1', 8080) service-side
Service Side
#_*_coding:utf-8_*___author__='Linhaifeng' fromSocketImport*Client=socket (Af_inet,sock_stream) client.connect (('127.0.0.1', 8080)) whiletrue:msg=input ('>>:'). Strip ()if  notMsgContinueclient.send (Msg.encode ('Utf-8')) msg=CLIENT.RECV (1024)    Print(Msg.decode ('Utf-8'))
Client
 fromThreadingImportThread fromSocketImport*ImportThreadingdefClient (Server_ip,port): C=socket (Af_inet,sock_stream)#The socket object must be added to the function, that is, within the local namespace, in the outside of the function is shared by all threads, then everyone common one socket object, then the client port is always the sameC.connect ((server_ip,port)) Count=0 whileTrue:c.send (('%s Say hello%s'% (Threading.current_thread (). GetName (), count)). Encode ('Utf-8')) msg=C.RECV (1024)        Print(Msg.decode ('Utf-8')) Count+=1if __name__=='__main__':     forIinchRange (500): T=thread (target=client,args= ('127.0.0.1', 8080) ) T.start ()
Multithreading concurrent multiple clients

Python Concurrent Programming Association Process

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.