#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
функцией