この章では、Python におけるコルーチンの役割と同時実行性について紹介し、コルーチン使用の長所と短所、および gevent 同時実行フレームワークの役割を理解できるようにします。一定の参考値があるので、困っている友達は参考にしていただければ幸いです。
Coroutine
Coroutine はユーザー モードの軽量スレッドであり、マイクロスレッドとも呼ばれます。
コルーチンには独自のレジスタ コンテキストとスタックがあります。スケジュールを切り替えると、レジスタ コンテキストとスタックは別の場所に保存されます。切り替えを戻すと、以前に保存したレジスタ コンテキストとスタックが復元されます。したがって、コルーチンは最後の呼び出しの状態 (つまり、すべてのローカル状態の特定の組み合わせ) を保持できます。プロセスが再入するたびに、最後の呼び出しの状態に入ることと同じになります。前回終了時の状態 論理フローの場所
利点:
スレッド コンテキスト切り替えのオーバーヘッドなし
アトミック操作のロックと同期のオーバーヘッドなし
制御フローを簡単に切り替え、プログラミング モデルを簡素化します
高い同時実行性、高いスケーラビリティ、低コスト: CPU が数十のプロセッサをサポートすることは問題ではありません。何千ものコルーチン。したがって、高度な同時処理に非常に適しています。
いわゆるアトミック操作は、スレッド スケジューリング メカニズムによって中断されない操作を指します。この操作は、一度開始されると、コンテキスト スイッチ (スイッチ) なしで最後まで実行されます。別のスレッドへ)。
アトミック操作は 1 ステップまたは複数ステップで行うことができますが、順序を崩したり、実行された部分のみを切断したりすることはできません。全体として見ることが原子性の核心です。
欠点:
マルチコアリソースを利用できない: コルーチンの本質はシングルスレッドであり、単一の CPU の複数のコアを同時に使用することはできません。コルーチンは、複数の CPU で実行するにはプロセスが連携する必要があります。もちろん、私たちが日常的に作成するアプリケーションのほとんどは、CPU を大量に使用するアプリケーションでない限り、この必要性はありません。
ブロッキング操作 (IO など) を実行すると、プログラム全体がブロックされます
Gevent を使用します
gevent は Python の同時実行フレームワークであり、コアとしてマイクロスレッド Greenlet を備え、epoll イベント リスニング メカニズムやその他の多くの最適化を使用して効率化しています。:
簡単な例
gevent のスリープは制御を引き継ぐことができます。ネットワークまたは IO によって制限されている関数で gevent を使用すると、これらの関数は協調的にスケジュールされます。gevent の真の機能は次のとおりです。解き放たれた。 Gevent はすべての詳細を処理して、可能な場合にはネットワーク ライブラリが暗黙的に実行権限を greenlet コンテキストに引き渡すようにします。
import gevent def foo(): print('running in foo') gevent.sleep(0) print('com back from bar in to foo') def bar(): print('running in bar') gevent.sleep(0) print('com back from foo in to bar') # 创建线程并行执行程序 gevent.joinall([ gevent.spawn(foo), gevent.spawn(bar), ])
実行結果:
同期非同期
import random import gevent def task(pid): gevent.sleep(random.randint(0, 2) * 0.001) print('Task %s done' % pid) def synchronous(): for i in range(1, 10): task(i) def asynchronous(): threads = [gevent.spawn(task, i) for i in range(10)] gevent.joinall(threads) print('Synchronous:') synchronous() print('Asynchronous:') asynchronous()
実行出力:
import gevent from gevent import Greenlet class Test(Greenlet): def __init__(self, message, n): Greenlet.__init__(self) self.message = message self.n = n def _run(self): print(self.message, 'start') gevent.sleep(self.n) print(self.message, 'end') tests = [ Test("hello", 3), Test("world", 2), ] for test in tests: test.start() # 启动 for test in tests: test.join() # 等待执行结束
IO 操作は非常に時間がかかるため、プログラムは待機状態になることがよくありますが、gevent がコルーチンを自動的に切り替えることで、Greenlet が IO を待機するのではなく常に実行されることが保証されます。
切り替えは IO 操作中に自動的に完了するため、gevent は Python に付属する標準ライブラリの一部を変更する必要があります。このプロセスは起動時のモンキー パッチによって完了します。
import gevent import requests from gevent import monkey monkey.patch_socket() def task(url): r = requests.get(url) print('%s bytes received from %s' % (len(r.text), url)) gevent.joinall([ gevent.spawn(task, 'https://www.baidu.com/'), gevent.spawn(task, 'https://www.qq.com/'), gevent.spawn(task, 'https://www.jd.com/'), ])
実行出力:
3 つのネットワーク操作が同時に実行され、終了順序が異なることがわかります。
以上がPython でのコルーチンと並行性の用途は何ですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。