Reputation: 8360
I am just playing around with threads in python and am quite new to python too. I have a producer class of whom I create threads. These thread all access a single object that is a common resource. Below is the code
class Producer (threading.Thread):
def __init__(self, threadId, source):
threading.Thread.__init__(self)
self.source = source
self.threadId = threadId
def produce(self):
while 1:
data = self.source.getData()
if data == False:
print "===== Data finished for "+self.threadId+" ====="
break
else:
print data
def run(self):
self.produce()
#class
class A:
def __init__(self):
self.dataLimit = 5
self.dataStart = 1
def getData(self):
lock = Lock()
lock.acquire()
if self.dataStart > self.dataLimit:
return False
lock.release()
data = "data from A :: "+str(self.dataStart)+" Accessor thread :: "+thread.threadId
time.sleep(0.5)
lock.acquire()
self.dataStart += 1
lock.release()
return data
#def
#class
source = A()
for i in range(2):
thread = Producer( "t_producer"+str(i), source )
thread.start()
print "Main thread exiting..."
So class A counts dataStart from 1 to 5. Now as it is a common resource and getData method implements locking too, threads of producer class will access getData method interchangeably and expected output is as follows:
data from A :: 1 Accessor thread :: t_producer0
data from A :: 2 Accessor thread :: t_producer1
data from A :: 3 Accessor thread :: t_producer1
data from A :: 4 Accessor thread :: t_producer0
data from A :: 5 Accessor thread :: t_producer0
===== Data finished for t_producer0 =====
===== Data finished for t_producer1 =====
But I am getting this:
data from A :: 1 Accessor thread :: t_producer0
data from A :: 1 Accessor thread :: t_producer1
data from A :: 3 Accessor thread :: t_producer1
data from A :: 3 Accessor thread :: t_producer1
data from A :: 5 Accessor thread :: t_producer1
===== Data finished for t_producer0 =====
data from A :: 5 Accessor thread :: t_producer1
===== Data finished for t_producer1 =====
As you can see data count is repeating, randomly count is missing. How to deal with this problem here?
Upvotes: 1
Views: 1793
Reputation: 1
def getData(self):
lock = threading.Lock()
with lock:
if self.dataStart > self.dataLimit:
return False
data = "data from A :: " + str(self.dataStart) + " Accessor thread :: " + thread.threadId
self.dataStart += 1
return data
Upvotes: -1
Reputation: 3520
def getData(self):
lock = Lock()
lock.acquire()
if self.dataStart > self.dataLimit:
return False
lock.release()
data = "data from A :: "+str(self.dataStart)+" Accessor thread :: "+thread.threadId
time.sleep(0.5)
You are returning False before the release call. Try using the with
statement like so:
with lock:
# Do stuff
This will make sure to acquire and then release it afterwards.
Upvotes: 4