У меня есть список в Python, который я всегда смотрю на его первый элемент, поработать с ним, а затем удалить этот первый элемент.
Однако в то же время новые элементы могут быть вставлены в этот список одновременно. Они также могут быть вставлены в положение [0]
как показано в следующем примере:
import threading
import time
class listener:
def __init__(self):
thread = threading.Thread(target=self.run, args=())
thread.daemon = True
thread.start()
def run(self):
while True:
if time.monotonic() >= Car.cars_list[0].time:
# other stuff happens to the 0th element
# what happens if a new element is insrted just now in car_list?
Cars.cars_list.pop(0)
class Car:
# list that is always sorted according to car time parameter
cars_list = []
def __init__(self, id, model, time):
self.id = id
self.model = model
self.time = time
# method that inserts the car to cars_list based on time with simple binary search
Car.insert(self, Carr.cars_list)
@staticmethod
def insert(x, a):
lo = 0
hi = len(a)
while lo < hi:
mid = (lo + hi) // 2
if x.time < a[mid].time:
hi = mid
else:
lo = mid + 1
a.insert(lo, x)
Что произойдет, если новая машина будет вставлена в 0-й элемент, когда слушатель делает что-то для текущего 0-го элемента.
Мне кажется, что мне нужно заблокировать изменение cars_list, когда я работаю над ним внутри цикла while True, включая строку pop (0).
Или возможно использовать некоторый тип буфера/очереди. Какие-либо предложения?
Если вам нужно (как в вашем примере), чтобы исследовать первый элемент, а затем, возможно, удалить его (и сделать дальнейшую обработку), вы должны принять блокировку вокруг осмотра и (потенциальные) удалений, но вы можете снять блокировку во время обработки ( это не относится к контейнеру).
Если вы всегда удаляете первый элемент, list.pop
уже является атомарным в Python. (Конечно, он может выдать, если список может быть (или станет) пустым.)
Также обратите внимание, что удаление из конца списка происходит намного быстрее, чем из начала.
cars_list[0]
в if
.