[Tutor] Variables in Threaded functions
lonetwin
lonetwin@yahoo.com
Fri, 12 Oct 2001 15:38:35 +0530
Hi everybody,
Thanx Boudewijn, for the quick answer. Now that I have fixed what I was
trying to do...I have some more questions for you (an' everybody who might
want to answer).
You wrote:
> If you want all threads to share something, you do need to have an
> object that is accessible to all of them. However, accessing a shared
> object from more than one thread at a time is a recipe for disaster,
> so you need to create a lock object, and acquire() that lock before
> every access.
Right, I though as much.
*********************************************
> This is how I rewrote your script:
> ----
> import threading, time
>
> class Strand(threading.Thread):
>
> def __init__(self, bag, lock):
> """The bag and the lock are shared objects,
> passed to the threads in their constructors. Another
> strategy is to make them global, but that's not half
> as neat."""
> threading.Thread.__init__(self)
> self.bag=bag
> self.lock=lock
<-------------------------snip-------------------------->
Question 1: why is bag passed to Strand ??....what if I bag belongs to be
the class ....like I did in my initial proggy ...is this a bad-thing in any
manner vvvvvvvvvvv
class Strand(threading.thread):
bag = range(100)
def __init__(self, lock):
.....
.....
<-------------------------/snip---------------------------->
> def run(self):
> # getName() tells us which thread is started
> print "Started " + self.getName()
> # We keep running until something gives us a break
> while 1:
> # We acquire the lock - in Java objects can be their own
> # locks, and you can synchronize() on an object. In Python
> # you need a separate lock object, and explicitly
> # acquire() that lock. If one thread accesses the
> # resources the lock is supposed to protect, without
> # acquiring it, then your concurrency is hosed. Caveat
> # delendor.
> self.lock.acquire()
> # Always encapsulate usage of the locked object in a
> # try... finally block: if the lock isn't released through
> # some exception, all other threads would be blocked.
> try:
> # If the bag is empty, we quit.
> if len(self.bag) == 0:
> break
> # Print the popped value
> print "thread", self.getName(), ": ", self.bag.pop()
> finally:
> # Whatever happens, always release the lock.
> self.lock.release()
<----------------------snip-------------------------------->
Question 2: Why ....
def run(self):
while 1:
self.acquire()
try:
if len(self.bag) == 0:
break
else:
doStuff()
finally:
self.lock.release()
.......
instead of ....
def run(self):
self.acquire()
try:
while len(self.bag) !=0:
doStuff()
finally:
self.lock.release()
For me, this ^^^^ reads much better....but is there something I should
know about ???
<---------------------------/snip---------------------->
> # Sleep a bit. A timeslice is long enough to pop the whole
> # bag in the first timeslice of the first thread.
> time.sleep(1)
>
> def main():
> Rope = []
> # The shared object and the shared lock
> sharedBagOfGoodies = range(100)
> sharedBagLock = threading.Lock()
>
> for x in range(3):
> thread = Strand(sharedBagOfGoodies, sharedBagLock)
> Rope.append(thread)
>
> for thread in Rope:
> print thread.getName()
> thread.start()
>
> print "done"
>
> if __name__ == '__main__':
> main()
> -------
And finally Question 3: What if I have more that one bag ?? does one lock,
lock-up all the shared objects ??....or should I lock.acquire() before every
access to any one of the shared objects ??
Hope my questions make sense...
Thanx for you patience
Peace
Steve
----------------------------------------------
Every oak tree started out as a
couple of nuts who stood their ground.
Anonymous
----------------------------------------------