Preventing tread collisions

Discussion in 'Python' started by Wanderer, Dec 12, 2012.

  1. Wanderer

    Wanderer Guest

    I have a program that has a main GUI and a camera. In the main GUI, you canmanipulate 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 thecameraActive 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 but my question is, is there a better way using semaphores, locks or something else to prevent collisions between threads?

    Thanks
    Wanderer, Dec 12, 2012
    #1
    1. Advertising

  2. Wanderer

    Dave Angel Guest

    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



    --

    DaveA
    Dave Angel, Dec 12, 2012
    #2
    1. Advertising

  3. Wanderer

    MRAB Guest

    On 2012-12-12 20:11, 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 but my question is, is there a better way using semaphores, locks or something else to prevent collisions between threads?
    >

    That suffers from a race condition in that self.cameraActive might be
    False when it's checked in the 'if' condition but set to True just
    afterwards by the other thread.

    You could try a non-blocking semaphore:

    def __init__(self):
    self.cameraActive = Semaphore()

    def onProperties(self, event):
    """ Display a message window with the camera properties
    event -- The camera properties menu event
    """
    # Update the temperature
    if self.cameraActive.acquire(False): # Non-blocking
    # Successfully acquired the semaphore, so the camera wasn't active
    self.camera.getTemperature()
    camDict = self.camera.getPropertyDict()
    self.cameraActive.release()
    else:
    camDict = {'Error': 'Camera Busy'}
    MRAB, Dec 12, 2012
    #3
  4. Wanderer

    Ian Kelly Guest

    On Wed, Dec 12, 2012 at 1:53 PM, MRAB <> wrote:
    > You could try a non-blocking semaphore:
    >
    > def __init__(self):
    > self.cameraActive = Semaphore()


    Why a Semaphore and not just a plain old Lock?
    Ian Kelly, Dec 12, 2012
    #4
  5. Wanderer

    MRAB Guest

    On 2012-12-12 20:58, Ian Kelly wrote:
    > On Wed, Dec 12, 2012 at 1:53 PM, MRAB <> wrote:
    >> You could try a non-blocking semaphore:
    >>
    >> def __init__(self):
    >> self.cameraActive = Semaphore()

    >
    > Why a Semaphore and not just a plain old Lock?
    >

    Good point. I probably thought of a semaphore because the OP mentioned
    it first. :)
    MRAB, Dec 12, 2012
    #5
  6. Am 12.12.2012 21:29, schrieb Dave Angel:
    > 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.


    I have a general question about this kinds of things. I see that the
    above is a common use case for some kind of lock which does this
    testing/locking atomically. But the question is: if I know for sure that
    there is no other thread that might get in the way this solution would
    be fine, right?

    In one of my applications i have a somewhat different case: i have a
    list of objects and call the same method of each object, each in its own
    thread (which is created and later joined just for this purpose). The
    objects are thus only used by that one thread, the main thread waits for
    all threads to be finished before accessing those objects again. Do i
    really need some kind of locking for those objects?

    Greetings
    Alexander Blinne, Dec 13, 2012
    #6
  7. >> 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.
    Andrew Robinson, Dec 13, 2012
    #7
  8. Wanderer

    Ian Kelly Guest

    On Thu, Dec 13, 2012 at 3:26 AM, Alexander Blinne <> wrote:
    > I have a general question about this kinds of things. I see that the
    > above is a common use case for some kind of lock which does this
    > testing/locking atomically. But the question is: if I know for sure that
    > there is no other thread that might get in the way this solution would
    > be fine, right?


    If you know for sure that there is no other thread, then there is no
    need for the flag in the first place.

    > In one of my applications i have a somewhat different case: i have a
    > list of objects and call the same method of each object, each in its own
    > thread (which is created and later joined just for this purpose). The
    > objects are thus only used by that one thread, the main thread waits for
    > all threads to be finished before accessing those objects again. Do i
    > really need some kind of locking for those objects?


    No, if a resource is only ever used by one thread/process, then there
    is no reason to lock it.
    Ian Kelly, Dec 13, 2012
    #8
  9. Wanderer

    Wanderer Guest

    On Wednesday, December 12, 2012 3:53:28 PM UTC-5, MRAB wrote:
    > On 2012-12-12 20:11, Wanderer wrote:
    >
    > > I have a program that has a main GUI and a camera. In the main GUI, youcan 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 separatethread, 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 setthe cameraActive to True just before starting the thread. I generate an event on exiting the thread which sets the cameraActive flag to False. I alsocheck 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 but my question is, is there a better way using semaphores, locks or something else to prevent collisions between threads?

    >
    > >

    >
    > That suffers from a race condition in that self.cameraActive might be
    >
    > False when it's checked in the 'if' condition but set to True just
    >
    > afterwards by the other thread.
    >
    >
    >
    > You could try a non-blocking semaphore:
    >
    >
    >
    > def __init__(self):
    >
    > self.cameraActive = Semaphore()
    >
    >
    >
    > def onProperties(self, event):
    >
    > """ Display a message window with the camera properties
    >
    > event -- The camera properties menu event
    >
    > """
    >
    > # Update the temperature
    >
    > if self.cameraActive.acquire(False): # Non-blocking
    >
    > # Successfully acquired the semaphore, so the camera wasn't active
    >
    > self.camera.getTemperature()
    >
    > camDict = self.camera.getPropertyDict()
    >
    > self.cameraActive.release()
    >
    > else:
    >
    > camDict = {'Error': 'Camera Busy'}


    Thanks. Why Non-blocking?
    Wanderer, Dec 13, 2012
    #9
  10. Wanderer

    Wanderer Guest

    On Wednesday, December 12, 2012 3:53:28 PM UTC-5, MRAB wrote:
    > On 2012-12-12 20:11, Wanderer wrote:
    >
    > > I have a program that has a main GUI and a camera. In the main GUI, youcan 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 separatethread, 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 setthe cameraActive to True just before starting the thread. I generate an event on exiting the thread which sets the cameraActive flag to False. I alsocheck 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 but my question is, is there a better way using semaphores, locks or something else to prevent collisions between threads?

    >
    > >

    >
    > That suffers from a race condition in that self.cameraActive might be
    >
    > False when it's checked in the 'if' condition but set to True just
    >
    > afterwards by the other thread.
    >
    >
    >
    > You could try a non-blocking semaphore:
    >
    >
    >
    > def __init__(self):
    >
    > self.cameraActive = Semaphore()
    >
    >
    >
    > def onProperties(self, event):
    >
    > """ Display a message window with the camera properties
    >
    > event -- The camera properties menu event
    >
    > """
    >
    > # Update the temperature
    >
    > if self.cameraActive.acquire(False): # Non-blocking
    >
    > # Successfully acquired the semaphore, so the camera wasn't active
    >
    > self.camera.getTemperature()
    >
    > camDict = self.camera.getPropertyDict()
    >
    > self.cameraActive.release()
    >
    > else:
    >
    > camDict = {'Error': 'Camera Busy'}


    Thanks. Why Non-blocking?
    Wanderer, Dec 13, 2012
    #10
  11. Wanderer

    Dave Angel Guest

    On 12/13/2012 11:36 AM, Wanderer wrote:
    > <snip>
    >
    > Thanks. Why Non-blocking?


    You said you didn't want the GUI to lock up. Non-blocking lets you
    choose alternative action when you would otherwise have to wait for the
    resource.



    --

    DaveA
    Dave Angel, Dec 13, 2012
    #11
  12. Wanderer

    Wanderer Guest

    On Thursday, December 13, 2012 11:54:10 AM UTC-5, Dave Angel wrote:
    > On 12/13/2012 11:36 AM, Wanderer wrote:
    >
    > > <snip>

    >
    > >

    >
    > > Thanks. Why Non-blocking?

    >
    >
    >
    > You said you didn't want the GUI to lock up. Non-blocking lets you
    >
    > choose alternative action when you would otherwise have to wait for the
    >
    > resource.
    >
    >
    >
    >
    >
    >
    >
    > --
    >
    >
    >
    > DaveA


    Thanks. I understand now.
    Wanderer, Dec 13, 2012
    #12
  13. Wanderer

    Wanderer Guest

    On Thursday, December 13, 2012 11:54:10 AM UTC-5, Dave Angel wrote:
    > On 12/13/2012 11:36 AM, Wanderer wrote:
    >
    > > <snip>

    >
    > >

    >
    > > Thanks. Why Non-blocking?

    >
    >
    >
    > You said you didn't want the GUI to lock up. Non-blocking lets you
    >
    > choose alternative action when you would otherwise have to wait for the
    >
    > resource.
    >
    >
    >
    >
    >
    >
    >
    > --
    >
    >
    >
    > DaveA


    Thanks. I understand now.
    Wanderer, Dec 13, 2012
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Howie
    Replies:
    4
    Views:
    341
    Howie
    Aug 21, 2003
  2. Vam
    Replies:
    2
    Views:
    296
    Andrey Tarasevich
    Feb 14, 2005
  3. Richard Bos
    Replies:
    3
    Views:
    360
    CBFalconer
    Feb 6, 2004
  4. Peter Ammon

    Avoiding name collisions in macros

    Peter Ammon, May 21, 2004, in forum: C Programming
    Replies:
    6
    Views:
    580
    Chris Torek
    May 23, 2004
  5. addicted.adi

    Tread Local Performance Metrics.

    addicted.adi, Jan 17, 2011, in forum: Java
    Replies:
    0
    Views:
    308
    addicted.adi
    Jan 17, 2011
Loading...

Share This Page