Before learning the asynchronous IO model, let's learn about the co-process
The process is also called micro-threading, Coroutine
A subroutine or a function, in all languages, is a hierarchy call, such as a call to B,b call C. C execution is finished, B is finished, and finally a is completed.
So a subroutine is implemented through a stack, and a thread is a subroutine that executes a sub-program.
Subroutine calls always return one entry at a time, the order of invocation is clear, and the calling and subroutine of the process are different.
The process appears to be a subroutine, but can be interrupted within the subroutine during execution, in turn, to execute another subroutine, returning execution at the appropriate time
Note that in a subroutine interrupt to execute other subroutines is not a function call, similar to a CPU interrupt, such as a subroutine A, b
defA ():Print('1') Print('2') Print('3')defB ():Print('x') Print('y') Print('Z')
Assuming that the process is executed by the coprocessor, it can be interrupted at any time during the execution of a, and the execution of b,b may be interrupted during execution to execute a, and the result may be:
xy3z
But in a there is no call B, so the call of the association is more difficult to understand than the function
It looks like a, b execution is multi-threaded, but the process is characterized by a thread execution, which has the advantage over multithreading.
The greatest advantage is the high execution efficiency of the process. Because the subroutine switch is not a thread switch, but is controlled by the program itself, so there is no cost of the off-the-shelf switching, the more threads are more likely to benefit from the process performance
The second advantage is that there is no need for a multi-threaded lock mechanism, because there is only one thread, there is no write variable conflict, in the process of controlling the shared resources are not locked, only need to determine the state is good,
So the execution efficiency is much higher than multithreading.
Because the process is a county, then the use of multi-core CPU you, the simplest way is the multi-process + association, that is, the full use of multi-core, and give full play to the high efficiency of the association, get very high performance,
Python multi-process support is implemented through generator.
In generator, not only can we iterate through a for loop, but we can constantly call next () to get the next value returned by the yield statement
But the yield of Python can not only return a value, it can also accept parameters emitted by the caller
See Example:
The traditional producer consumer model is a thread that writes messages to a thread to fetch messages, control the queue through a lock mechanism, and wait, but accidentally it could deadlock
If the use of the process, the producer after the production of the message, directly through yield jump to the consumer jump to the consumer to start execution, the customer after the completion of the loan, switch producers continue to produce, very high efficiency
defconsumer (): R="' whiletrue:n=yieldRif notN:return Print('[CONSUMER] consuming%s ...'%N) R='OK'defProduce (c): C.send (None) n=0 whileN < 5: N= n + 1Print('[PRODUCER] producing%s ...'%N) R=c.send (n)Print('[PRODUCER] Consumer return:%s'%r) c.close () C=consumer () produce (c)
[PRODUCER] Producing 1... [CONSUMER] Consuming1... [PRODUCER] Consumerreturn: 200Ok[producer] Producing2... [CONSUMER] Consuming2... [PRODUCER] Consumerreturn: 200Ok[producer] Producing3... [CONSUMER] Consuming3... [PRODUCER] Consumerreturn: 200Ok[producer] Producing4... [CONSUMER] Consuming4... [PRODUCER] Consumerreturn: 200Ok[producer] Producing5... [CONSUMER] Consuming5... [PRODUCER] Consumerreturn: $ OK
n = yield R is not an assignment statement, equivalent to:
if produce return nif consume return r
If produce calls send, it is equivalent to assigning n in consumer if consume calls yield R, which is equivalent to assigning r in produce
C.send (None) is used to start a generator and will error if the parameter does not pass to none. But it is also used only to start the generator, and does not call yield that is, when execution send (None) goes from produce to consume, only the previous sentence of yield R is executed
Notice that the consumer
function is a generator
, put one in consumer
produce
after:
First call the c.send(None)
startup generator;
Then, once the thing is produced, by c.send(n)
switching to consumer
execution;
consumer
By yield
getting the message, processing, and passing the yield
results back;
produce
Get consumer
The result of processing, continue to produce the next message;
produce
decided not to produce, by c.close()
closing consumer
, the whole process was over.
The entire process is unlocked, executed by one thread, produce
and the consumer
task is completed collaboratively, so called "co-process", rather than a thread-preemptive multi-tasking.
Finally, apply Donald Knuth's sentence to summarize the features of the process:
"Subroutine is a special case of the process. ”
Python Learning Notes Association