Как разделить объект между потоками? - PullRequest
1 голос
/ 05 июня 2019

У меня есть случай, когда объект из одного класса передается (как часть инициализации) другому классу.

Один из классов, вообще говоря, обновит объект, а другой выведет его (без изменений объекта). Это будет происходить в отдельных темах.

import threading
import time
import random

class Consumer:

    def __init__(self):
        self.data = []

    def print(self):
        while True:
            print(self.data)
            time.sleep(1)

class Producer:

    def __init__(self, data):
        self.data = data

    def update(self):
        while True:
            self.data.append(random.random())


consumer = Consumer()
producer = Producer(consumer.data)
threading.Thread(target=consumer.print).run()
threading.Thread(target=producer.update).run()

Я думал, что data и self.data (в обоих классах) в конечном итоге будут указывать на одни и те же данные, но это не так: на выходе получается набор [], который показывает, что изменения в Producer не отражены в Consumer.

Я, вероятно, в конечном итоге перепроектирую код, чтобы избежать подобных уловок, но мне бы очень хотелось понять, где произошла копия data (что объясняет, почему все не указывает на одну и ту же память)

1 Ответ

2 голосов
/ 05 июня 2019

Прежде всего - ссылка на данные одинакова, вы правильно их инициализируете. Вы можете проверить это, запустив print(consumer.data is producer.data) (это равенство ссылок питонов).

run() не создает отдельную тему. Он запускает функцию потока в контексте текущего потока, поэтому вы застряли в цикле печати consumer.print, и producer.update фактически никогда не вызывается

Вы должны позвонить .start() вместо:

import threading
import time
import random

class Consumer:

    def __init__(self):
        self.data = []

    def print(self):
        while True:
            print(self.data)
            time.sleep(1)

class Producer:

    def __init__(self, data):
        self.data = data

    def update(self):
        while True:
            self.data.append(random.random())
            time.sleep(1)


consumer = Consumer()
producer = Producer(consumer.data)
threading.Thread(target=consumer.print).start()
threading.Thread(target=producer.update).start()
...