Странный вывод двух параллельных потоков - PullRequest
1 голос
/ 25 марта 2020

мой код он запускает 2 потока с внутренними планировщиками, которые печатают номер каждую секунду

import threading
import time
from datetime import datetime

import schedule

_lock = threading.Lock()


def p(number):
    _lock.acquire()
    print(number, datetime.now())
    _lock.release()


def f(number):
    schedule.every(5).seconds.do(p, number)
    while True:
        schedule.run_pending()
        time.sleep(1)


thread = threading.Thread(target=f, args=(1,))
thread2 = threading.Thread(target=f, args=(2,))
thread.start()
thread2.start()

ожидаемый вывод

1 2020-03-25 22:07:17.817528
2 2020-03-25 22:07:17.817528
1 2020-03-25 22:07:22.821887
2 2020-03-25 22:07:22.821887
1 2020-03-25 22:07:27.826093
2 2020-03-25 22:07:27.826093

фактический вывод (см. 4 вместо 2 отпечатков на 17 'и 3 вместо 2 отпечатков на 27 ')

1 2020-03-25 22:07:17.817528
2 2020-03-25 22:07:17.817528
1 2020-03-25 22:07:17.817528
2 2020-03-25 22:07:17.817528
1 2020-03-25 22:07:22.821887
2 2020-03-25 22:07:22.821887
1 2020-03-25 22:07:27.826093
2 2020-03-25 22:07:27.826093
2 2020-03-25 22:07:27.826093

На самом деле я не знаю, почему иногда триггеры потока работают более одного раза. Есть идеи, что я делаю не так?

1 Ответ

2 голосов
/ 25 марта 2020

У вас есть то, что называется состояние гонки . Два потока пытаются записать в stdout (т.е. print) одновременно, но порядок, в котором они могут получить этот ресурс, зависит от времени планировщика.

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

Измените свой код следующим образом :

import threading
# ...

_lock = threading.Lock()

def p(number):
    _lock.acquire()
    print(number, end='')
    _lock.release()

# ...

https://docs.python.org/3.8/library/threading.html#threading .Lock

...