93

スレッド化と並行性の基本を理解しようとしています。2 つのスレッドが 1 つの共有リソースに繰り返しアクセスしようとする単純なケースが必要です。

コード:

import threading

class Thread(threading.Thread):
    def __init__(self, t, *args):
        threading.Thread.__init__(self, target=t, args=args)
        self.start()
count = 0
lock = threading.Lock()

def increment():
    global count 
    lock.acquire()
    try:
        count += 1    
    finally:
        lock.release()
   
def bye():
    while True:
        increment()
        
def hello_there():
    while True:
        increment()

def main():    
    hello = Thread(hello_there)
    goodbye = Thread(bye)
    
    while True:
        print count

if __name__ == '__main__':
    main()

したがって、2 つのスレッドがあり、どちらもカウンターをインクリメントしようとしています。increment()スレッド「A」が を呼び出すと、lockが確立され、「A」が解放されるまで「B」がアクセスできなくなると思いました。

を実行すると、そうではないことが明らかになります。ランダムなデータ レース風のインクリメントをすべて取得します。

ロックオブジェクトは正確にどのように使用されますか?

さらに、スレッド関数内にロックを配置しようとしましたが、まだ運がありません。

4

2 に答える 2

121

プロセスを遅くしてロックをもう少しブロックすると、ロックを使用しているときにロックがほとんど機能していることがわかります。重要なコード部分をロックで囲むという正しい考えがありました。これは、例を少し調整して、それぞれがロックを解放するのを待つ方法を示しています。

import threading
import time
import inspect

class Thread(threading.Thread):
    def __init__(self, t, *args):
        threading.Thread.__init__(self, target=t, args=args)
        self.start()

count = 0
lock = threading.Lock()

def incre():
    global count
    caller = inspect.getouterframes(inspect.currentframe())[1][3]
    print "Inside %s()" % caller
    print "Acquiring lock"
    with lock:
        print "Lock Acquired"
        count += 1  
        time.sleep(2)  

def bye():
    while count < 5:
        incre()

def hello_there():
    while count < 5:
        incre()

def main():    
    hello = Thread(hello_there)
    goodbye = Thread(bye)


if __name__ == '__main__':
    main()

出力例:

...
Inside hello_there()
Acquiring lock
Lock Acquired
Inside bye()
Acquiring lock
Lock Acquired
...
于 2012-05-09T23:11:36.300 に答える