У меня проблемы с пониманием блокировок в Python - PullRequest
0 голосов
/ 14 октября 2019

Я играю с threading.Lock и написал следующий тест для моего понимания.

import threading
from time import sleep

LOCK = threading.Lock()

class Printer(threading.Thread):
    def __init__(self, *args, **kwargs):
        super(Printer, self).__init__(*args, **kwargs)
        self.i = 0

    def run(self):            
        while True:
            print(self.i)
            self.i += 1
            sleep(1)

p = Printer()
p.start()

raw_input() # block main thread until return pressed
LOCK.acquire()

# stop printer for 6 seconds
for _ in range(3):
    print('holding...')
    sleep(2)

# let printer continue
LOCK.release()

Я ожидал следующий вывод (комментарий не является частью вывода):

0
1
2
# user pressed enter
holding...
holding...
holding...
3
4
5
...

Однако принтер не останавливается - фактический вывод, который я получаю:

0
1
2
# user pressed enter
holding...
3
4
holding...
5
6
holding...
7
8
...

Очевидно, что я что-то здесь неправильно понимаю? Как я могу временно приостановить работу принтера?

1 Ответ

1 голос
/ 14 октября 2019

Вы также должны получить блокировку в своей ветке. Замок сам по себе ничего не делает. Его единственная цель - сделать так, чтобы вы не могли получить блокировку дважды - таким образом, делая две или более части кода взаимоисключающими. Тот, кто получает блокировку, может продолжить работу, пока любой другой поток блокирует попытки получить блокировку.

Рассмотрим эту версию кода (я использую with, но вы также можете заменить ее на получение / освобождение.

import threading
from time import sleep

LOCK = threading.Lock()

class Printer(threading.Thread):
    def __init__(self, *args, **kwargs):
        super(Printer, self).__init__(*args, **kwargs)
        self.i = 0

    def run(self):
        while True:
            with LOCK:
                print(self.i)
                self.i += 1
            sleep(1)

p = Printer()
p.start()

raw_input() # block main thread until return pressed
LOCK.acquire()

# stop printer for 6 seconds
for _ in range(3):
    print('holding...')
    sleep(2)

# let printer continue
LOCK.release()

Это теперь делает то, что вы хотите.

Это все еще не "правильно", так как ваш основной поток завершает работу, как только снимает блокировку. Обычно это считаетсяплохое программирование, но в демо-сценарии это, вероятно, не имеет значения. Вы просто больше не управляете своим потоком - он будет работать там до тех пор, пока не будет убит сигналом.

...