Попробуйте: запишите модуль в том месте, где находится ваша функция, и, если вход в функцию таков, что требуется блокировка, получите блокировку внутри функции. В противном случае не надо.
l = threading.RLock()
def fn(arg):
if arg == arg_that_needs_lock:
l.acquire()
try:
# do stuff
finally:
l.release()
else:
# do other stuff
EDIT
Насколько я могу судить сейчас, вопрос заключается в том, как запретить двум любым потокам одновременно выполнять одну и ту же функцию с одним и тем же аргументом. Однако нет проблем с двумя потоками, выполняющими одну и ту же функцию с разными аргументами одновременно. Простой способ сделать это, если все допустимые аргументы функции могут быть словарными ключами, - создать словарь аргументов для блокировок:
import threading
dict_lock = threading.RLock()
locks = {}
def fn_dict(arg):
dict_lock.acquire()
try:
if arg not in dict:
locks[arg] = threading.RLock()
l = locks[arg]
finally:
dict_lock.release()
l.acquire()
try:
# do stuff
finally:
l.release()
Если ваша функция может быть вызвана с множеством разных аргументов, это будет означать много блокировок. Вероятно, лучшим способом было бы иметь набор всех аргументов, с которыми в данный момент выполняется функция, и защитить содержимое этого набора с помощью блокировки. Я думаю, что это должно работать:
set_condition = threading.Condition()
current_args = set()
def fn_set(arg):
set_condition.acquire()
try:
while arg in current_args:
set_condition.wait()
current_args.add(arg)
finally:
set_condition.release()
# do stuff
set_condition.acquire()
try:
current_args.remove(arg)
set_condition.notifyAll()
finally:
set_condition.release()