Общий объект блокировки потоков Python не работает должным образом

#python #multithreading #thread-safety #locking #shared-memory

#питон #многопоточность #потокобезопасность #блокировка #разделяемая память

Вопрос:

У меня есть два или более потоков, созданных из одного и того же класса с именем ‘Player’, совместно использующих memory_buffer.

 class Player(Thread):
    def __init__(self, player_number, memory_buffer):
        super().__init__()
        self.memory_buffer = memory_buffer
        self.player_number = player_number
        self.lock = Lock()

    def add_data(self, count):
        with self.lock:
            self.memory_buffer.add_data(self.player_number, count)

    def run(self):
        count = 0
        while True:
            self.add_data(count)
            count  = 1
 

Где memory_buffer — это объект, как показано ниже:

 class MemoryBuffer:
    def __init__(self, max_size=int(1e6)):
        self.player_count = np.zeros((max_size, 2)) - 1
        self.ptr = 0


    def add_data(self, player_number, count):
        self.player_count[self.ptr] = [player_number, count]
        self.ptr  = 1
 

Затем я запускаю поток

 num_player = 5
memory_buffer = MemoryBuffer(max_size=int(1e6))
players = [Player(player_number=i   1, memory_buffer=memory_buffer) for i in range(5)]
for p in players:
    p.start()
 

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

Например, I когда у игрока 1 уже есть до 1000 memory_buffer.player_count должен иметь такие значения от 0 до 999, хотя последовательность прерывается каким-либо другим потоком игрока. Но часть значения отсутствовала, и я распечатал журналы, а затем увидел, что часть потока иногда перезаписывается в позиции memory_buffer.ptr. Пример приведен ниже

 Memory buffer data that is produced by player 1: [[1, 0], [1, 1], [1, 2], ... , [1, 999]] 
Missing buffer data: [[1, 7], [1, 157]]
 

Похоже, что блокировка работает неправильно. Может кто-нибудь помочь мне работать правильно?

Комментарии:

1. вы используете блокировки для каждого игрока, вместо блокировки для каждого буфера памяти переместите блокировку в сам буфер памяти

2. Я тоже пробовал эту версию, но по-прежнему возникали те же проблемы.

3. покажите код для этого, тогда мы сможем увидеть, в чем проблема. в настоящее время нет причин для того, чтобы эти блокировки когда-либо работали так, как вы хотите

4. Что произойдет, если вы попробуете self.lock.acquire() и self.lock.release() до, и после кода, который требует блокировки?

5. Хорошо, @AntiMatterDynamite вы правы. Похоже, мне нужно использовать экземпляр блокировки везде, а не разные экземпляры здесь и там. В настоящее время я перепроверяю, и кажется, что он будет работать до тех пор, пока используемый экземпляр блокировки является одним и тем же экземпляром для каждого игрока…

Ответ №1:

в настоящее время блокировки управляются в Player классе, что означает, что каждый игрок инициализирует и использует другой Lock объект, вы должны переместить проверку блокировки в MemoryBuffer класс, где она будет управляться самой add_data функцией