[Tutor] Changing instance attributes in different threads

Kent Johnson kent37 at tds.net
Tue Feb 7 12:02:45 CET 2006


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



More information about the Tutor mailing list