如何跨所有实例创建同步函数 [英] How to create a synchronized function across all instances
问题描述
我想针对类的所有实例上的某些CRUD函数在python中创建一个同步方法.例如,当create被线程调用并正在进行时,delete需要在同一对象上等待.
I want to create a synchronized method in python with respect to some CRUD functions on all instances of a class. For example while create is called and ongoing by a thread, delete needs to wait on the same object.
有人可以告诉我下面的代码是否正确.我可能会遇到一些语法错误,但是我想知道的是,在创建此类的所有实例的调用中,锁是否将相同,因此,是否正在进行任何实例创建/删除,请在相同或其他实例上进行删除/创建.由另一个线程实例将不得不等待吗?
Can someone please tell me if the code below is correct. I may have some syntax error but what I want to know is if the lock is going to be the same across calls to create ALL instances of this class and therefore if any instance create/delete is in progress delete/create on the same or other instances by another thread will have to wait?
import threading
import functools
def synchronized(wrapped):
lock = threading.Lock()
@functools.wraps(wrapped)
def _wrap(*args, **kwargs):
with lock:
return wrapped(*args, **kwargs)
return _wrap
class AtomicCRUD(object):
@synchronized
def create(self):
#Do stuff that may take a while here.
pass
@synchronized
def delete(self):
#Do stuff that may take a while here.
pass
我对python同步的理解将为每个create/delete函数对象调用. 我在锁定对象的上面的同步函数中添加了一条打印语句,并使用以下命令进行了测试:
My understanding of python is synchronized will be called for each of create/delete function object. I put a print statement in the synchronized function above for the lock object and did a test run using the following:
@synchronized
def test1():
print "test1"
@synchronized
def test2():
print "test2"
我得到以下输出,这使我认为两个函数对象使用的锁是相同的.我似乎不明白它是如何工作的.
And I get the following output, which makes me think the lock used is the same for both function objects. I don't seem to understand how this works.
<Semaphore c=1 _w[0]>
<Semaphore c=1 _w[0]>
test1
test2
推荐答案
您的输出将打印相同的<Semaphore c=1 _w[0]>
,但不一定表示这些对象是相同的对象.这取决于您的print
语句.
Your output prints the same <Semaphore c=1 _w[0]>
but it doesn't necessarily indicate that those are the same objects. It depends what your print
statement is.
要确保您没有使用相同的Lock
对象,可以在_wrap
函数中添加print
语句,如下所示:
To make sure you are not using the same Lock
object you could add a print
statement in the _wrap
function as follow:
def synchronized(wrapped):
lock = threading.Lock()
@functools.wraps(wrapped)
def _wrap(*args, **kwargs):
print "Calling '%s' with Lock %s" % (wrapped.__name__, id(lock))
with lock:
return wrapped(*args, **kwargs)
return _wrap
每次您都会打印出一个不同的 id
呼叫create
或delete
:
You will get a different id
printed every time you call create
or delete
:
AtomicCRUD().delete()
# Calling 'delete' with Lock 3075170560
AtomicCRUD().delete()
# Calling 'delete' with Lock 3075170560
AtomicCRUD().create()
# Calling 'create' with Lock 3075170544
AtomicCRUD().create()
# Calling 'create' with Lock 3075170544
装饰器synchronized
仅调用两次-当解释器读取装饰的方法声明时.装饰器使用_wrap
的实现替换"装饰的方法,但不替换functools.wraps(wrapped)
之上的内容,因此Lock
每个装饰方法仅创建一次.
The decorator synchronized
is only call twice - when the interpreter reads the decorated method declaration. The decorator "replace" the decorated method with the implementation of _wrap
but not with what is above functools.wraps(wrapped)
so the Lock
is only created once per decorated method.
每个装饰方法都有自己的Lock
.
Each decorated method has its own Lock
.
在上面的代码中,我们还可以看到它适用于AtomicCRUD
的任何实例,因为我们每次都重新实例化一个对象,但是使用单个实例时结果是相同的
In the code above we can also see that this works for any instance of AtomicCRUD
since we re-instantiate an object every time but the result is the same when using a single instance
crud = AtomicCRUD()
crud.delete()
# Calling 'delete' with Lock 3075059968
crud.delete()
# Calling 'delete' with Lock 3075059968
crud.create()
# Calling 'create' with Lock 3075059952
crud.create()
# Calling 'create' with Lock 3075059952
通过一个完整的示例,我们可以看到Lock
的行为符合预期:
And with a complete example we can see that the Lock
s behave as expected:
import threading
import functools
import time
def synchronized(wrapped):
lock = threading.Lock()
print lock, id(lock)
@functools.wraps(wrapped)
def _wrap(*args, **kwargs):
with lock:
print ("Calling '%s' with Lock %s from thread %s [%s]"
% (wrapped.__name__, id(lock),
threading.current_thread().name, time.time()))
result = wrapped(*args, **kwargs)
print ("Done '%s' with Lock %s from thread %s [%s]"
% (wrapped.__name__, id(lock),
threading.current_thread().name, time.time()))
return result
return _wrap
class AtomicCRUD(object):
@synchronized
def create(self):
#Do stuff that may take a while here.
time.sleep(1)
@synchronized
def delete(self):
#Do stuff that may take a while here.
time.sleep(1)
class SyncThread(threading.Thread):
def __init__(self, crud, name):
super(self.__class__, self).__init__(name=name)
self._crud = crud
def run(self):
self._crud.create()
self._crud.delete()
crud = AtomicCRUD()
threads = [SyncThread(crud, "Thread_%d" % i) for i in range(5)]
for t in threads:
t.start()
for t in threads:
t.join()
输出显示不能同时从不同的线程调用create
.但是delete
和create
可以从不同的线程同时调用.
The output shows that create
cannot be called at the same time from different threads. But delete
and create
can be called at the same time from different thread.
这篇关于如何跨所有实例创建同步函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!