Python-threading. Hoe vergrendel ik een discussie?

Ik probeer de basisprincipes van threading en gelijktijdigheid te begrijpen. Ik wil een eenvoudig geval waarin twee threads herhaaldelijk proberen toegang te krijgen tot één gedeelde bron.

De code:

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 incre():
    global count 
    lock.acquire()
    try:
        count += 1    
    finally:
        lock.release()
def bye():
    while True:
        incre()
def hello_there():
    while True:
        incre()
def main():    
    hello = Thread(hello_there)
    goodbye = Thread(bye)
    while True:
        print count
if __name__ == '__main__':
    main()

Dus ik heb twee threads, die beide proberen de teller te verhogen. Ik dacht dat als thread ‘A’ incre()zou noemen, het lockzou worden ingesteld, waardoor ‘B’ geen toegang zou krijgen totdat ‘A’ is losgelaten.

Als u de run uitvoert, wordt duidelijk dat dit niet het geval is. Je krijgt alle willekeurige gegevens race-achtige stappen.

Hoe wordt het lock-object precies gebruikt?

Bewerken, daarnaast heb ik geprobeerd de sloten in de threadfuncties te plaatsen, maar nog steeds geen geluk.


Antwoord 1, autoriteit 100%

Je kunt zien dat je sloten vrijwel werken terwijl je ze gebruikt, als je het proces vertraagt en ze een beetje meer laat blokkeren. Je had het juiste idee, waar je kritische stukjes code omringt met het slot. Hier is een kleine aanpassing aan uw voorbeeld om u te laten zien hoe de een op de ander wacht om het slot te ontgrendelen.

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()

Voorbeelduitvoer:

...
Inside hello_there()
Acquiring lock
Lock Acquired
Inside bye()
Acquiring lock
Lock Acquired
...

Antwoord 2

import threading 
# global variable x 
x = 0
def increment(): 
    """ 
    function to increment global variable x 
    """
    global x 
    x += 1
def thread_task(): 
    """ 
    task for thread 
    calls increment function 100000 times. 
    """
    for _ in range(100000): 
        increment() 
def main_task(): 
    global x 
    # setting global variable x as 0 
    x = 0
    # creating threads 
    t1 = threading.Thread(target=thread_task) 
    t2 = threading.Thread(target=thread_task) 
    # start threads 
    t1.start() 
    t2.start() 
    # wait until threads finish their job 
    t1.join() 
    t2.join() 
if __name__ == "__main__": 
    for i in range(10): 
        main_task() 
        print("Iteration {0}: x = {1}".format(i,x))

Other episodes