Hans Dushanthakumar wrote:
> Hi,
>    In a multithreaded program, how do I ensure that a block of code in a
> thread is always executed fully before passing control to another
> thread. Does "Lock" serve this purpose?

No, not exactly. It is used to prevent threading errors but not in the way you 
think.

Acquiring a Lock, by itself, doesn't prevent another thread from running. It 
just prevents another thread from acquiring *the same* lock. So to prevent two 
bits of code from running "at the same time" you can use a *single* Lock. 
Change your code to use a global Lock or pass the Lock to the class 
constructors. 

You will also have to handle waiting on a full Queue; if you just use a shared 
lock you will deadlock if you put_num() on a full Queue. (put_num.run() will 
acquire the lock, then it will block waiting for room in the Queue. 
get_num.run() will not be able to acquire the lock so the Queue will never 
empty.) Take a look at Queue.py to see one way to handle this.

Note that Queue is already thread-safe for insertion and removal. If you really 
need to read the size as you do in your code then you need another Lock but the 
basic Queue does not need this.

You might be interested in "The Little Book of Semaphores" which is an 
introduction to threading using Python.
http://greenteapress.com/semaphores/

Kent

> 
> The foll program is a dummy one, with 2 threads. One put a number onto a
> queue (of max size 1) and the other thread reads from the que.
> 
> However, on running this program (Win XP, NOT via IDLE - it hangs when I
> run it thru IDLE) the output that I see on screen indicates that the
> block of code within the lock aquire and release was not run completely
> before the other thread started running. Note that the print messages
> from the 2 threads seem to be interspersed together:
> 
> 
> import threading
> import Queue
> 
> class put_num(threading.Thread):
>     stop_thread = 0
> 
>     def __init__(self, num, que):
>         threading.Thread.__init__(self)
>         self.que = que
>         self.num = num
>         self.lock = threading.Lock()
>         
>     def run(self):
>         global stop_thread
>         for k in range (20):
>             self.lock.acquire()
>             print "put_num: ", self.num
>             self.que.put(str(self.num))
>             print "put_num: Que size = ", self.que.qsize()
>             self.num = self.num + 1
>             self.lock.release()
> 
> class get_num(threading.Thread):
>     stop_thread = 0
> 
>     def __init__(self, que):
>         threading.Thread.__init__(self)
>         self.que = que
>         self.lock = threading.Lock()
>         
>     def run(self):
>         global stop_thread
>         for k in range (20):
>             self.lock.acquire()
>             mynum = self.que.get()
>             print "get_num: ", mynum
>             print "get_num: Que size = ", self.que.qsize()
>             self.lock.release()
> 
> my_que = Queue.Queue(1)
> 
> put_num_thread = put_num(742, my_que)
> get_num_thread = get_num(my_que)
> 
> print "Starting threads"
> put_num_thread.start()
> get_num_thread.start()
> 
> print "Waiting for threads to finish"
> put_num_thread.join()
> get_num_thread.join()
> 
> print "Closing down"
> raw_input("\n\nPress enter to Quit: ")
> 
> 
> 
> 
> This is the out put of the above program:
> 
> 
> 
> Starting threads
> put_num:  742
> Waiting for threads to finish
> put_num: Que size =  1
> get_num:  742
> get_num: Que size =  0
> put_num:  743
> put_num: Que size =  1
> get_num:  743
> get_num: Que size =  0
> put_num:  744
> put_num: Que size =  1
> get_num:  744
> get_num: Que size =  0
> put_num:  745
> put_num: Que size =  1
> get_num:  745
> get_num: Que size =  0
> put_num:  746
> put_num: Que size =  1
> get_num:  746
> get_num: Que size =  0
> put_num:  747
> put_num: Que size =  get_num:  747
> get_num: Que size =  0
> 0
> put_num:  748
> put_num: Que size =  1
> get_num:  748
> get_num: Que size =  0
> put_num:  749
> put_num: Que size =  get_num:  749
> get_num: Que size =  0
> 0
> put_num:  750
> put_num: Que size =  1
> get_num:  750
> get_num: Que size =  0
> put_num:  751
> put_num: Que size =  1
> get_num:  751
> get_num: Que size =  0
> put_num:  752
> put_num: Que size =  get_num:  752
> get_num: Que size =  0
> 0
> put_num:  753
> put_num: Que size =  1
> get_num:  753
> get_num: Que size =  0
> put_num:  754
> put_num: Que size =  1
> get_num:  754
> get_num: Que size =  0
> put_num:  755
> put_num: Que size =  get_num:  755
> get_num: Que size =  0
> 0
> put_num:  756
> put_num: Que size =  get_num:  756
> get_num: Que size =  0
> 0
> put_num:  757
> put_num: Que size =  get_num:  757
> get_num: Que size =  0
> 0
> put_num:  758
> put_num: Que size =  1
> get_num:  758
> get_num: Que size =  0
> put_num:  759
> put_num: Que size =  get_num:  759
> get_num: Que size =  0
> 0
> put_num:  760
> put_num: Que size =  1
> get_num:  760
> get_num: Que size =  0
> put_num:  761
> put_num: Que size =  get_num:  761
> get_num: Que size =  0
> 0
> Closing down
> 
> 
> Press enter to Quit:
> _______________________________________________
> Tutor maillist  -  Tutor@python.org
> http://mail.python.org/mailman/listinfo/tutor
> 

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

Reply via email to