Python threading with queue: how to avoid to use join?

后端 未结 1 2040
星月不相逢
星月不相逢 2021-01-26 14:34

I have a scenario with 2 threads:

  1. a thread waiting for messages from a socket (embedded in a C library - blocking call is "Barra.ricevi") then putting

相关标签:
1条回答
  • 2021-01-26 15:18

    This is likely because your Barra does not release the global interpreter lock (GIL) when Barra.ricevi. You may want to check this though.

    The GIL ensures that only one thread can run at any one time (limiting the usefulness of threads in a multi-processor system). The GIL switches threads every 100 "ticks" -- a tick loosely mapping to bytecode instructions. See here for more details.

    In your producer thread, not much happens outside of the C-library call. This means the producer thread will get to call Barra.ricevi a great many times before the GIL switches to another thread.

    Solutions to this are to, in terms of increasing complexity:

    • Call time.sleep(0) after adding an item to the queue. This yields the thread so that another thread can run.
    • Use sys.setcheckinterval() to lower the amount of "ticks" executed before switching threads. This is will come at the cost of making the program much more computationally expensive.
    • Use multiprocessing rather than threading. This includes using multiprocessing.Queue instead of Queue.Queue.
    • Modify Barra so that it does release the GIL when its functions are called.

    Example using multiprocessing. Be aware that when using multiprocessing, your processes no longer have an implied shared state. You will need to have a look at multiprocessing to see how to pass information between processes.

    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)
    
    0 讨论(0)
提交回复
热议问题