I don't understand what is happening in this threading code

Nir nir1408 at gmail.com
Sun Jan 20 14:29:49 CET 2008


On Jan 19, 2:43 am, Matthew Wilson <m... at tplus1.com> wrote:
> In this code, I tried to kill my thread object by setting a variable on it
> to False.
>
> Inside the run method of my thread object, it checks a different
> variable.
>
> I've already rewritten this code to use semaphores, but I'm just curious
> what is going on.
>
> Here's the code:
>
> import logging, threading, time
> logging.basicConfig(level=logging.DEBUG,
>                     format="%(threadName)s: %(message)s")
>
> class Waiter(threading.Thread):
>     def __init__(self, hot_food):
>         super(Waiter, self).__init__()
>         self.should_keep_running = True
>         self.hot_food = hot_food
>
>     def run(self):
>         while self.should_keep_running:
>             logging.debug("Inside run, the id of should_keep_running is %s."
>                           % id(self.should_keep_running))
>             self.hot_food.acquire()
>
> def cook_food(hot_food):
>     i = 5
>     while i >= 0:
>         logging.debug("I am cooking food...")
>         time.sleep(1)
>         hot_food.release()
>         logging.debug("Andiamo!")
>         i -= 1
>
> def main():
>
>     hot_food = threading.Semaphore(value=0)
>
>     chef = threading.Thread(name="chef", target=cook_food, args=(hot_food, ))
>     chef.start()
>
>     w = Waiter(hot_food)
>     logging.debug("Initially, the id of w.should_keep_running is %s."
>               % id(w.should_keep_running))
>     w.start()
>     logging.debug("After start, the id of w.should_keep_running is %s."
>               % id(w.should_keep_running))
>
>     # Wait for the chef to finish work.
>     chef.join()
>
>     # Now try to kill off the waiter by setting a variable inside the waiter.
>     w.should_keep_running = False
>     logging.debug("Now, the id of w.should_keep_running is %s."
>                   % id(w.should_keep_running))
>
> if __name__ == "__main__":
>     main()
>
> And here's what I get when I execute it.  I have to suspend the process
> with CTRL=Z and then kill -9 it.
>
> $ python foo.py
> MainThread: Initially, the id of w.should_keep_running is 135527852.
> MainThread: After start, the id of w.should_keep_running is 135527852.
> chef: I am cooking food...
> Thread-1: Inside run, the id of should_keep_running is 135527852.
> chef: Andiamo!
> chef: I am cooking food...
> Thread-1: Inside run, the id of should_keep_running is 135527852.
> chef: Andiamo!
> chef: I am cooking food...
> Thread-1: Inside run, the id of should_keep_running is 135527852.
> chef: Andiamo!
> chef: I am cooking food...
> Thread-1: Inside run, the id of should_keep_running is 135527852.
> chef: Andiamo!
> chef: I am cooking food...
> Thread-1: Inside run, the id of should_keep_running is 135527852.
> chef: Andiamo!
> chef: I am cooking food...
> Thread-1: Inside run, the id of should_keep_running is 135527852.
> chef: Andiamo!
> Thread-1: Inside run, the id of should_keep_running is 135527852.
> MainThread: Now, the id of w.should_keep_running is 135527840.
>
> [1]+  Stopped                 python foo.py
>
> $ kill -9 %1
>
> [1]+  Stopped                 python foo.py
>
> The memory address of should_keep_running seems to change when I set it
> from True to False, and inside the run method, I keep checking the old
> location.
>
> I am totally baffled what this means.
>
> Like I said earlier, I already rewrote this code to use semaphores, but
> I just want to know what is going on here.
>
> Any explanation is welcome.
>
> TIA
>
> Matt

It does not check a different variable.
You can open a Python session and try the following:

Python 2.5.1 (r251:54863, Oct  5 2007, 13:36:32)
[GCC 4.1.3 20070929 (prerelease) (Ubuntu 4.1.2-16ubuntu2)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> a = True
>>> id(a)
135527852
>>> a = False
>>> id(a)
135527840

The problem is that the waiter is locked waiting for new food and
never looks at the variable.
You should add hot_food.release() after you set the keep running flag
to False.

Nir




More information about the Python-list mailing list