Ответ 1
Это, скорее всего, потому, что ваш Barra
не освобождает глобальную блокировку интерпретатора (GIL), когда Barra.ricevi
. Возможно, вы захотите проверить это.
GIL гарантирует, что только один поток может запускаться в любой момент времени (ограничивая полезность потоков в многопроцессорной системе). GIL переключает потоки каждые 100 "тиков" - тик свободно привязывается к инструкциям байткода. Подробнее см. здесь.
В потоке производителя не так много происходит за пределами вызова C-библиотеки. Это означает, что продюсерский поток получит вызов Barra.ricevi
много раз, прежде чем GIL переключится на другой поток.
Решения для этого - с точки зрения возрастающей сложности:
- Вызов
time.sleep(0)
после добавления элемента в очередь. Это дает поток, чтобы другой поток мог работать. - Используйте
sys.setcheckinterval()
для уменьшения количества "тиков", выполняемых перед переключением потоков. Это будет зависеть от того, что программа будет намного дороже вычислить. - Используйте
multiprocessing
, а неthreading
. Это включает использованиеmultiprocessing.Queue
вместоQueue.Queue
. - Измените
Barra
так, чтобы он освобождал GIL при вызове его функций.
Пример с помощью multiprocessing
. Имейте в виду, что при использовании многопроцессорности ваши процессы больше не имеют подразумеваемого общего состояния. Вам нужно будет взглянуть на многопроцессорность, чтобы увидеть, как передавать информацию между процессами.
import Barra
import multiprocessing
def threadCAN(posQu):
while True:
canMsg = Barra.ricevi("can0")
if canMsg[0] == 'ERR':
print(canMsg)
else:
print("Enqueued message", canMsg)
posQu.put(canMsg)
if __name__ == "__main__":
posQu = multiprocessing.Queue(maxsize=0)
procCan = multiprocessing.Process(target=threadCAN, args=(posQu,))
procCan.daemon = True
procCan.start()
while True:
posMsg = posQu.get()
print("Messagge from the queue", posMsg)