Michael Lange wrote:
> I have used a boolean to control access to a variable that is used by two 
> threads,
> as in this example:
> 
> thread 1 does:
> 
>     while self.locked:
>         pass
>     self.locked = 1
>     if condition:
>         self.name = 'bob'
>     else:
>         self.name = 'mike'
>     self.locked = 0
> 
> thread 2 does:
> 
>     while self.locked:
>         pass
>     self.locked = 1
>     n = self.name
>     self.locked = 0
>     if n == 'bob':
>         <do something>
>     else:
>         <do something else>
> 
> I *thought* this would be safe, but now reading this thread I start to doubt.
> Are there any pitfalls I overlooked in this technique?

If the intent is to ensure that only one thread at a time will be in the 
code where self.locked == 1, this code will not ensure that. 
Test-and-set code needs a lock to be thread safe.

Imagine both threads reach 'while self.locked' when self.locked == 0. 
Both threads might finish the while loop before either one sets 
self.locked. Then both threads might continue through to 'self.locked = 
0' together.

In this case I'm not sure what would happen if the above scenario took 
place; it might be harmless. But your lock is definitely not doing what 
you think it is.

One way to make this code thread-safe is to use a threading.Condition() 
instead of a boolean variable:

thread 1 does:

     self.lock.acquire()
     if condition:
         self.name = 'bob'
     else:
         self.name = 'mike'
     self.lock.release()

thread 2 does:

     self.lock.acquire()
     n = self.name
     self.lock.release()
     if n == 'bob':
         <do something>
     else:
         <do something else>

If this is the only communication or synchronization between the two 
threads I don't think the lock is needed at all - thread 2 is presumably 
in a loop and thread 1 is controlling the behaviour of the loop 
asynchronously. If there is some other kind of synchronization between 
the loops, and thread 2 is only supposed to run once for each setting of 
self.name in thread 1, you could use Condition.wait() and 
Condition.notify() to do the synchronization.

Kent

_______________________________________________
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor

Reply via email to