On Nov 23, 2015, at 11:51 AM, Ian Kelly <ian.g.ke...@gmail.com> wrote:
> 
> On Mon, Nov 23, 2015 at 12:55 PM, Ian Kelly <ian.g.ke...@gmail.com> wrote:
>> On Mon, Nov 23, 2015 at 10:54 AM, Israel Brewster <isr...@ravnalaska.net> 
>> wrote:
>>> Concern: Since the master process is multi-threaded, it seems likely enough 
>>> that multiple threads on the master side would make requests at the same 
>>> time. I understand that the Queue class has locks that make this fine (one 
>>> thread will complete posting the message before the next is allowed to 
>>> start), and since the child process only has a single thread processing 
>>> messages from the queue, it should process them in order and post the 
>>> responses (if any) to the master_queue in order. But now I have multiple 
>>> master processes all trying to read master_queue at the same time. Again, 
>>> the locks will take care of this and prevent any overlapping reads, but am 
>>> I guaranteed that the threads will obtain the lock and therefore read the 
>>> responses in the right order? Or is there a possibility that, say, thread 
>>> three will get the response that should have been for thread one? Is this 
>>> something I need to take into consideration, and if so, how?
>> 
>> Yes, if multiple master threads are waiting on the queue, it's
>> possible that a master thread could get a response that was not
>> intended for it. As far as I know there's no guarantee that the
>> waiting threads will be woken up in the order that they called get(),
>> but even if there are, consider this case:
>> 
>> Thread A enqueues a request.
>> Thread B preempts A and enqueues a request.
>> Thread B calls get on the response queue.
>> Thread A calls get on the response queue.
>> The response from A's request arrives and is given to B.
>> 
>> Instead of having the master threads pull objects off the response
>> queue directly, you might create another thread whose sole purpose is
>> to handle the response queue. That could look like this:
>> 
>> 
>> request_condition = threading.Condition()
>> response_global = None
>> 
>> def master_thread():
>>    global response_global
>>    with request_condition:
>>        request_queue.put(request)
>>        request_condition.wait()
>>        # Note: the Condition should remain acquired until
>> response_global is reset.
>>        response = response_global
>>        response_global = None
>>    if wrong_response(response):
>>        raise RuntimeError("got a response for the wrong request")
>>    handle_response(response)
>> 
>> def response_thread():
>>    global response_global
>>    while True:
>>        response = response_queue.get()
>>        with request_condition:
>>            response_global = response
>>            request_condition.notify()
> 
> Actually I realized that this fails because if two threads get
> notified at about the same time, they could reacquire the Condition in
> the wrong order and so get the wrong responses.
> 
> Concurrency, ugh.
> 
> It's probably better just to have a Condition/Event per thread and
> have the response thread identify the correct one to notify, rather
> than just notify a single shared Condition and hope the threads wake
> up in the right order.

Tell me about it :-) I've actually never worked with conditions or 
notifications (actually even this bi-drectional type of communication is new to 
me), so I'll have to look into that and figure it out. Thanks for the 
information!

> -- 
> https://mail.python.org/mailman/listinfo/python-list

-- 
https://mail.python.org/mailman/listinfo/python-list

Reply via email to