如何跨所有实例创建同步函数

2024-05-12 23:02:04 发布

您现在位置:Python中文网/ 问答频道 /正文

我想在python中创建一个与类的所有实例上的一些CRUD函数相关的同步方法。例如,当create被线程调用并正在进行时,delete需要等待同一个对象。在

有人能告诉我下面的代码是否正确。我可能有一些语法错误,但我想知道的是,在创建这个类的所有实例的调用中,锁是否相同,因此,如果任何实例create/delete正在进行,那么另一个线程在同一个或其他实例上的delete/create必须等待?在

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的理解是同步的,将调用每个创建/删除函数对象。我将print语句放在上面锁对象的synchronized函数中,并使用以下命令进行了测试运行:

^{pr2}$

我得到了下面的输出,这使我认为两个函数对象使用的锁是相同的。我好像不明白这是怎么回事。在

<Semaphore c=1 _w[0]>
<Semaphore c=1 _w[0]>
test1
test2

Tags: 对象实例函数importlockdefcreateargs
1条回答
网友
1楼 · 发布于 2024-05-12 23:02:04

您的输出输出输出相同的<Semaphore c=1 _w[0]>,但并不一定表示这些是相同的对象。这取决于您的print语句是什么。在

为了确保没有使用相同的Lock对象,可以在_wrap函数中添加print语句,如下所示:

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

每次调用createdelete时,都会打印不同的{a1}:

^{pr2}$

当解释器读取修饰方法声明时,decoratorsynchronized只调用两次。decorator用_wrap的实现“替换”装饰方法,而不是使用上面的functools.wraps(wrapped)的实现,因此每个修饰方法只创建一次{}。在

每个修饰方法都有自己的Lock。在

在上面的代码中,我们还可以看到,这对AtomicCRUD的任何实例都有效,因为我们每次都会重新实例化一个对象,但使用单个实例时结果是相同的

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的行为与预期一致:

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和{}可以同时从不同的线程调用。在

相关问题 更多 >