Preventing tread collisions

Andrew Robinson andrew3 at r3dsolutions.com
Thu Dec 13 15:32:18 CET 2012


>> On 12/12/2012 12:29 PM, Dave Angel wrote:
>>> On 12/12/2012 03:11 PM, Wanderer wrote:
>>>> I have a program that has a main GUI and a camera. In the main GUI,
>>>> you can manipulate the images taken by the camera. You can also use
>>>> the menu to check the camera's settings. Images are taken by the
>>>> camera in a separate thread, so the long exposures don't block the
>>>> GUI. I block conflicts between the camera snapshot thread and the
>>>> main thread by setting a flag called self.cameraActive. I check to
>>>> see if the cameraActive flag is false and set the cameraActive to
>>>> True just before starting the thread. I generate an event on exiting
>>>> the thread which sets the cameraActive flag to False. I also check
>>>> and set and reset the flag in all the menu commands that access the
>>>> camera. Like this.
>>>>
>>>>       def onProperties(self, event):
>>>>           """ Display a message window with the camera properties
>>>>           event -- The camera properties menu event
>>>>           """
>>>>           # Update the temperature
>>>>           if not self.cameraActive:
>>>>               self.cameraActive = True
>>>>               self.camera.getTemperature()
>>>>               camDict = self.camera.getPropertyDict()
>>>>               self.cameraActive = False
>>>>           else:
>>>>               camDict = {'Error': 'Camera Busy'}
>>>>           dictMessage(camDict, 'Camera Properties')
>>>>
>>>> This works
>>> I don't think so.  in between the if and the assignment, another thread
>>> could get in there and also set the flag.  Then when either one of them
>>> finishes, it'll clear the flag and the other code is unprotected.
>>>
>>> For semaphores between multiple threads, you either have to define only
>>> a single thread at any given moment being permitted to modify it, or you
>>> have to use lower-level primitives, sometimes called test+set operation.
>>>
>>> i don't know the "right" way to do this in Python, but this isn't it.
>>>> but my question is, is there a better way using semaphores, locks or
>>>> something else to prevent collisions between threads?
>>>>
>>>> Thanks

if you already have the cameraActive variable reset by an event at
thread termination; it's not necessary to set it false in the menu
command.  It's better NOT to do that. Your GUI menu functions need only
test to see if self.cameraActive is false, and then set it to true just
before the launch of the second thread.  The second thread, itself,
ought never change the cameraActive variable.

I'm also not sure why you are able to obtain the information from the
camera sequentially (camDict?) when you say you are not blocking the GUI.
I  assume self.camera.getTemperature() launches the second thread ?  Is it,
somehow, explicitly allowing the continued processing of GUI events that
accessing the camera straight in the GUI would not allow?

If you are talking about the Python semaphore library, I don't think you
need it.

Semaphores are really for use when multiple threads wish to access a
resource where more than one thread can use the resource at a time;
That would mean multiple threads using the camera at once... not a good
idea.

The Lock() object essentially does the same thing, but assumes only 1
thread may use it at a time; hence that would be sufficient (if it
were needed at all!).

A lock is in the "thread" library (Python 2.xx) or the "threading"
library (Python 3.xx).  Semaphores aren't part of the thread library in
Python 2.xx... (another reason not to bother with them...)

However, Locking will cause the GUI thread to block when the camera is
in use, which isn't what you want -- correct?

There is a way to test the lock but not block, which is equivalent to
your variable (to be honest!);  I'm pretty sure that Python doesn't use
true Posix threads but only the GNU Pth library.  That means that the
only time threads truly switch is determined by the Python interpreter.
In that case, all python variable assignments are going to be effectively
atomic anyhow... and a variable, like you are using, is identical to a lock.
(Atomic merely means the write can't be interrupted by a thread switch partway
through).

If you have a multi-processing environment, there is a multiprocessor
library -- where the lock or semaphore mechanism would be important.
But I really don't think you need it.

  




More information about the Python-list mailing list