123 base coroutine

First, threads, processes review

  1. In the operating system process is the smallest unit of resource allocation, the thread is the smallest unit CPU scheduling.

  2. Concurrent nature: + switching state of preservation.

  3. cpu running a task, perform other tasks around the cut in both cases (the forced switching is controlled by the operating system), a case that a blockage has occurred task, another task is that the calculation time is too long.

  4. Introducing process theory, mention The three implementation status of the process, and the thread is the execution unit, so it can be understood as the figure three states threads.

  5. Concurrent which does not enhance the efficiency, just to let the rain descends cpu be able to achieve all tasks seem to be "simultaneous" implementation of the results, if multiple tasks are pure calculation, but will reduce the efficiency of this switch.

Second, co-Production Process

Coroutine : the concurrent single-threaded, also called micro-threads, shred. English Coroutine.

What is a word description coroutine : coroutine lightweight thread is a user-state, i.e. coroutine is controlled by the user program scheduling themselves, concurrency single thread.

It is emphasized that :

  1. python threads belonging to the kernel level, that is controlled by the operating system scheduler (such as single-threaded execution time is too long or encounter io will be forced to surrender cpu execute permissions, switch to another thread running)
  2. Open coroutines within a single thread, the event io, will (non-independent handover and efficiency !!! io operations) from the application level (rather than the operating system) control switch, in order to improve efficiency

Comparative OS switching control thread, the user switches coroutine controlled within a single thread.

Key : when it came to switching io makes sense

Specifically : coroutine concept is essentially abstracted from the programmer, the operating system does not know the coroutine existence, it will say a thread of my own experience io inside my own thread cut directly onto their other tasks, and operations with this system can not be found, that is, to achieve the highest efficiency under a single thread.

Advantages :

  1. Coroutine switching overhead is smaller, program-level switching part of the operating system is completely imperceptible, and thus more lightweight
  2. You can achieve the effect of concurrent use of the maximum single-threaded cpu

Disadvantages :

  1. Nature coroutine is single-threaded, multi-core can not be used, a program may be more open process, open multiple threads within each process, open coroutine within each thread, you have to detect all io, whenever there is a blockage overall and went obstruction.
  2. Coroutine refer to a single thread, then once a coroutine blocking occurs, no switching tasks, will block the entire thread

Features :

  1. It must be implemented concurrently in only a single thread in
  2. Modify shared data without locking
  3. Save your user program control flow stack multiple contexts
import time
def eat():
    print('eat 1')
    # 疯狂的计算呢没有io
    time.sleep(2)
    # for i in range(100000000):
    #     i+1
def play():
    print('play 1')
    # 疯狂的计算呢没有io
    time.sleep(3)
    # for i in range(100000000):
    #     i+1
play()
eat() # 5s

In a single-threaded, the use to implement coroutine yield, this is a no sense of Ctrip (because we said coroutine to do in case there is io makes sense)

import time
def func1():
    while True:
        1000000+1
        yield

def func2():
    g = func1()
    for i in range(100000000):
        i+1
        next(g)

start = time.time()
func2()
stop = time.time()
print(stop - start) # 17.68560242652893

The above comparison yeild switch running time, but we alone than take more time-consuming serial execution function, so to achieve the above Ctrip does not make sense.

import time

def func1():
    for i in range(100000000):
        i+1
def func2():
    for i in range(100000000):
        i+1

start = time.time()
func1()
func2()
stop = time.time()
print(stop - start) # 12.08229374885559

Third, the nature of the coroutine

Coroutine is in the nature of single-threaded, controlled by the user's own task encounters a blocked io switched to another task to perform, in order to improve efficiency. To achieve it, we need to find a way solutions that meet the following criteria at the same time:

  1. You may control the switching between a plurality of tasks, prior to the handover status of the task will be saved, so that re-run, it is possible to continue based on the position of pause.
  2. Supplement 1: io can detect operation, switching occurs only in the case where the operation face io

3.1 coroutine we need to use genvent module

Key: Use gevent to implement coroutines is possible, but we said coroutine main IO is experiencing makes sense, but just can not do this gevent module coroutine real meaning, that this module while he undetectable IO

但用gevent模块是检测不到IO的,也就是说这样写同样是没有意义的

The following procedures in the gevent is a class

  1. gevent.spawn nature calls static methods spawn gevent.greenlet.Greenlet class:

    @classmethod
    def spawn(cls, *args, **kwargs):
        g = cls(*args, **kwargs)
        g.start()
        return g
  2. This class method calls Greenlet two function classes, * __ init _ * _ and start init function in the most critical is the code: 

    def __init__(self, run=None, *args, **kwargs):
       greenlet.__init__(self, None, get_hub()) # 将新创生的greenlet实例的parent一律设置成hub
       if run is not None:
       self._run = run
# 在这段程序我们发现,这段程序并没有实现遇见IO的时候,用户模cpu实现任务切换
import gevent
import time

def eat():
    print('eat 1')
    time.sleep(2)
    print('eat 2')
def play():
    print('play 1')
    # 疯狂的计算呢没有io
    time.sleep(3)
    print('play 2')

start = time.time()
g1 = gevent.spawn(eat)
g2 = gevent.spawn(play)
g1.join()
g2.join()
end = time.time()
print(end-start) 5.0041022300720215

'''
结果:
eat 1
eat 2
play 1
play 2
5.004306077957153
'''

Key Two: Use gevent of a patch to achieve, to achieve a truly meaningful coroutine by gevent class, the true realization of the user in to the operating system can not find a way to simulate the IO encountered when switching back and forth between tasks realization

Note: Here Again, the essential meaning coroutine is achieved in a single-threaded task of saving the state Gache change , and real coroutine must be met in the case of IO

from gevent import monkey;monkey.patch_all()
import gevent
import time

def eat():
    print('eat 1')
    time.sleep(2)
    print('eat 2')
def play():
    print('play 1')
    # 疯狂的计算呢没有io
    time.sleep(3)
    print('play 2')

start = time.time()
g1 = gevent.spawn(eat)
g2 = gevent.spawn(play)
g1.join()
g2.join()
end = time.time()
print(end-start)# 3.003168821334839

'''
结果:
eat 1
play 1
eat 2
play 2
3.003168821334839
'''

Guess you like

Origin www.cnblogs.com/xichenHome/p/11569119.html