Вопрос по multithreading, python – Python Threading. Как мне заблокировать тему?

51

Я пытаюсь понять основы многопоточности и параллелизма. Я хочу простой случай, когда два потока неоднократно пытаются получить доступ к одному общему ресурсу.

Код:

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

Итак, у меня есть два потока, оба пытаются увеличить счетчик. Я думал, что если нить 'A'; называетсяincre(),lock будет установлен, предотвращая "B"; от доступа до «A»; выпустил.

Запуск дает понять, что это не так. Вы получаете все случайные приращения данных.

Как именно используется объект блокировки?

Изменить. Кроме того, я пытался установить блокировки внутри потоковых функций, но все равно не повезло.

@ Игнасио Васкес-Абрамс - Должен сейчас. Я оставилif __name__ немного. Это то, что вы имели в виду? Zack
Вы используете блокировку правильно. Что заставляет вас думать, что это не так? jdi
Ваш код не работает. Ignacio Vazquez-Abrams
Это также не работает для меня. Я ожидаю, что ваше создание потока будет выглядеть так:hello = threading.Thread(target=hello_there) а затем для начала потокаhello.start(). Steven Rumbalski
Знаете ли вы, что вы можете использоватьwith lock: скорее, чемlock.acquire(); try: ...; finally: lock.release()? Chris Morgan

Ваш Ответ

1   ответ
61

что ваши блокировки в значительной степени работают, когда вы их используете, если вы замедлите процесс и заставите их блокировать немного больше. У вас была правильная идея, где вы блокируете критические фрагменты кода с помощью замка. Вот небольшая настройка вашего примера, чтобы показать вам, как каждый ожидает от другого, чтобы снять блокировку.

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
...
Так с блокировкой ждет, когда она станет доступной?
@Zack: Да, я полагаю, это был главный шутник, который смущал тебя У него не было никаких ограничений, поэтому он печатал быстрее, чем нити даже меняли его.
О, аккуратно! Я думаю, что я был смущенprint count вmain() показывая ошибочную итерацию. Но я полагаю, что отчасти из-за того, что у меня одновременно было три цикла. Спасибо! Также TIL о проверке модуля. Очень круто. Zack
@jdi Я пытаюсь понять блокировку, поэтому я добавил print (count) в вашу функцию приращения сразу после count + = 1, но когда я запускаю код, он становится равным 6?
@ErinGoBragh, потому что у нас есть два потока, пытающихся вызвать incre (), в то время как счетчик меньше 5. Один получает блокировку, и счет становится 5. Затем блокировка снимается, и другой поток проходит, и счет становится 6. Если было очень важно поддерживать счет на уровне 5 или меньше, вам нужно будет проверить счет после того, как вы получите замок, и ничего не делать, если он 5

Похожие вопросы