5

私のテスト コードは次のとおりです。

gevent コルーチンの実行は、1 つの CPU 命令に分割して実行するのではなく、"count + = 1" で実行されますか?

# -*- coding: utf-8 -*-
import threading

use_gevent = True        
use_debug = False        
cycles_count = 100*10000


if use_gevent:
    from gevent import monkey
    monkey.patch_thread()

count = 0


class Counter(threading.Thread):
    def __init__(self, name):
        self.thread_name = name
        super(Counter, self).__init__(name=name)

    def run(self):
        global count
        for i in xrange(cycles_count):
            if use_debug:
                print '%s:%s' % (self.thread_name, count)
            count = count + 1

counters = [Counter('thread:%s' % i) for i in range(5)]
for counter in counters:
    counter.start()
for counter in counters:
    counter.join()

print 'count=%s' % count
4

1 に答える 1

5

複合割り当て (+=) は Python ではアトミックではありません。gevent はそれを変更しません。

gevent コルーチンはシステム スレッドではなく、gevent のコンテキスト スイッチは OS によって制御されず、スレッドがブロックされる (io が発生する) まで gevent は切り替えられないため、gevent パッチを適用したスレッドを使用した場合のカウントは常に 5,000,000 です。

通常のスレッドの場合、状況は異なります。複合割り当てには 3 つのステップ (a. 値の読み取り、b. 値の増加、c. 変更された値の割り当て) が含まれており、これらのステップ間でスレッドの切り替えが発生する可能性があります。

以下のコードを確認してください。無限ループを実行する新しいスレッドを追加します。通常のスレッドの場合、os はスレッドを自動的に切り替えるため、count を出力できます。ただし、gevent スレッドの場合、count は出力されません。これは、Infinite スレッドが実行されると終了せず、IO が発生しないため gevent が他のスレッドに切り替わらないためです。

# -*- coding: utf-8 -*-
import threading

use_gevent = True        
use_debug = False        
cycles_count = 100
if use_gevent:
    from gevent import monkey
    monkey.patch_thread()

count = 0

class Counter(threading.Thread):
    def __init__(self, name):
        self.thread_name = name
        super(Counter, self).__init__(name=name)

    def run(self):
        global count
        for i in xrange(cycles_count):
            if use_debug:
                print '%s:%s' % (self.thread_name, count)
            if use_gevent:
                print self.thread_name
            count = count + 1

class Infinite(threading.Thread):
    def run(self):
        if use_gevent:
            print 'Infinite ...'
        while True:
            pass


counters = [Counter('thread:%s' % i) for i in range(5)]
for counter in counters:
    counter.start()
infinite = Infinite()
infinite.start()
for counter in counters:
    counter.join()

print 'count=%s' % count 
于 2013-10-29T03:45:02.760 に答える