繁体   English   中英

如何使用线程根据上次访问时间控制对函数的访问?

[英]How to control the access to a function based on the last access time using threads?

我想根据自上次访问以来经过的时间来控制对函数的访问。

为此,我实现了以下装饰器,它可以在单线程执行中完美运行:

import time

MIN_ELAPSED_TIME = 0.4
time_last_get = time.time()

def timingRequests(f):
    def wrapper(*args, **kwargs):
        global time_last_get  
        elapsed_time_since_last_get = time.time() - time_last_get
        if elapsed_time_last_request < MIN_REQUEST_TIME: # not enough time has passed since the last request
          time.sleep(MIN_REQUEST_TIME - elapsed_time_last_request)

        # At this point, at least MIN_ELAPSED_TIME has passed since last get
        time_last_get = time.time()
        r = f(*args, **kwargs)
        return r
    return wrapper

@timingRequests
doGet()

我想让 n 个线程(现在 2 个)访问这个函数并考虑线程之间的 time_last_get。 我的问题是每个线程都在等待根据自己之前执行的 doGet() 执行 doGet()

我尝试使用 threading.Event() 作为信号量, threading.Lock() 但仍然两个线程几乎同时访问该函数。

使用 2 个或更多线程时的行为是每个线程都根据同一线程的 time_last_get 等待执行 doGet(),而不是考虑其他线程的访问。

我想要实现的行为是下一个:

线程 1:doGet()

线程 2:等待(如有必要)自线程 2 访问以来经过的 MIN_ELAPSED_TIME 秒

线程 2:doGet()

线程 1:等待(如有必要)自线程 2 访问以来经过的 MIN_ELAPSED_TIME 秒

线程 1:doGet()

线程 1:等待(如有必要)自线程 1 访问以来经过的 MIN_ELAPSED_TIME 秒

我想通了是什么问题。

首先,我确实通过使用 threading.Events() 实例绕过了这个问题:

import time

MIN_ELAPSED_TIME = 0.4
time_last_get = time.time()
e = threading.Event()
e.set()

def timingRequests(f):
    def wrapper(*args, **kwargs):
        e.wait()
        e.clear()
        global time_last_get  
        elapsed_time_since_last_get = time.time() - time_last_get
        if elapsed_time_last_request < MIN_REQUEST_TIME: # not enough time has passed since the last request
          time.sleep(MIN_REQUEST_TIME - elapsed_time_last_request)

        # At this point, at least MIN_ELAPSED_TIME has passed since last get
        time_last_get = time.time()
        r = f(*args, **kwargs)
        e.set()
        return r
    return wrapper

@timingRequests
doGet()

但是我仍然很难理解为什么这个解决方案有效,但没有使用锁。

嗯,问题是这样的:

def timingRequests(f):
    def wrapper(*args, **kwargs):
        with threading.Lock():
            # Code

到达这部分代码的每个线程都在创建一个(未锁定的)threading.Lock() 实例,因此锁没有按预期工作。 然后解决方案是在timingRequests函数之外创建锁并以这种方式使用它:

lock = threading.Lock()

def timingRequests(f):
    def wrapper(*args, **kwargs):
        with lock:
            # Code

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM