I am working with locks within a class to avoid multiple threads adding the same elements to a list twice. However, my class gets stuck when I want to access a method protected by a lock from within the class itself.
The class looks like this (simplified, so it does not make much sense anymore):
import threading
class List(object):
def __init__(self):
self.list = []
self.lock = threading.Lock()
def add(self, element):
print("adding")
with self.lock:
if not element in self.list:
self.list.append(element)
def get(self):
print("getting")
with self.lock:
# Try to get more elements, might fail
if len(self.list) == 0:
self.getFromDb()
if len(self.list) > 0:
el = self.list.pop()
return el
else:
return None
def getFromDb(self):
print("getting from db")
# Emulate an hardcoded database ;)
self.add("i am new")
# Here we will enter a block that is already locked by
# the thread who called get() so my method waits
# infinitely
So the following test file does not complete as it gets stuck when it wants to add new elements to the list:
list = List()
print("= 1 =")
list.add("hi")
print("= 2 =")
print(list.get())
print("= 3 =")
print(list.get())
print("= 4 =")
Output is:
= 1 =
adding
adding
= 2 =
getting
hi
= 3 =
getting
getting from db
adding
There you can see that all methods are working, but when a new element shall be added from getFromDb (called from the locked block inside add) who itself calls add again, the application cannot continue.
Are there other methods than just filling the list directly in getFromDb without using add? This would not be that nice, as add does checking for duplicates (already in this very basic example).
You will need a recursive lock.
There is one in python’s
threading– see here.