自动化测试平台化[v1.0.0][事件资源锁]

在资源设计中,所有的资源从配置文件中读出后成为实例保存,通常情况下资源的名字是唯一的,因此可以通过资源名作为的锁的关键字,然后使用一个结构体来保存相应资源的锁信息,并使用信号量来标识锁状态

假设线程A对该资源进行操作,重置了信号量,当线程B也需要使用该资源并对其进行加锁的时候,就会因为该资源所对应的信号量而阻塞住线程,直到该信号量被线程A置位,代表线程A对该资源的占用结束,线程B才能继续

from core.result.logger import logger
from core.utilities.time import get_local_time
from threading import Event, Thread
import time


class ResourceIsLocked(Exception):
    def __init__(self, resource, event, timeout):
        super().__init__(f"Resource {resource} is locked by {event} and not released in {timeout}s")


class InvalidLockOperation(Exception):
    pass


class ResourceLockPool:
    """
    资源锁池
    """
    def __init__(self, log=None):
        self.log = log if log is not None else logger.register("ResourceLockPool", default_level="INFO")
        self.resource = dict()

    def lock(self, resource, event, timeout=60):
        """
        锁定资源
        """
        if resource.name in self.resource:
            lock = self.resource[resource.name]['lock']
            event_name = self.resource[resource.name]['event']
            if not lock.wait(timeout):
                raise ResourceIsLocked(resource.name, event_name, timeout)
        self.log.info(f"Lock {resource.name}: time: {get_local_time()}")
        self.resource[resource.name] = {
            "event": event,
            "date": get_local_time(),
            "lock": Event()
        }

    def release(self, resource, event):
        """
        释放资源
        """
        if resource.name in self.resource:
            if self.resource[resource.name]['event'] == event:
                self.log.info(f"Release lock for {resource.name}")
                self.resource[resource.name]['lock'].set()
                self.resource.pop(resource.name)
            else:
                raise InvalidLockOperation(
                    f"{resource.name} is locked by {self.resource[resource.name]['event']}")
        else:
            raise InvalidLockOperation(f'{resource.name} is not locked')

if __name__ == "__main__":

    class TestResource:
    	"""
    	代表测试资源类
    	"""
        def __init__(self, name):
            self.name = name


    log = logger.register("testlog")
    pool = ResourceLockPool(log)
    device1 = TestResource('device1')

	"""
	测试:定义两个方法,用来在两个线程中对同一个资源进行访问
	"""
    def test_method1():
        pool.lock(device1, "event1")
        log.info("method1 start")
        time.sleep(10)
        pool.release(device1, "event1")
        log.info("method1 stop")


    def test_method2():
        pool.lock(device1, "event2")
        log.info("method2 start")
        time.sleep(10)
        pool.release(device1, "event2")
        log.info("method2 stop")



    thread1 = Thread(target=test_method1)
    thread2 = Thread(target=test_method2)

    threads = [thread1, thread2]
    for t in threads:
        t.start()

    for t in threads:
        t.join()
  • ResourceLockPool中的resource字典类型的属性用于存放资源锁,资源锁的值被定义为一个字典类型的结构体,包含3个key,event表示占用该资源的事件名称,date表示锁产生的时间,lock用来存放信号量,为了和event事件区分开,使用lock来表示
  • lock方法用于加锁,该方法首先判断资源是否在resource属性中,如果存在则表示该资源已经被上锁,这时就需要调用该资源对应的信号量的wait方法,等待其他线程设置该信号
  • 引入超时时间防止死锁,超过设定时间后该信号量得不到置位,则wait方法返回False,抛出异常,告诉lock方法的调用者在超时时间内,资源锁无法释放
  • release方法用于释放资源,如果资源不在resouce属性中,则抛出异常,告诉调用者资源没有被锁,否则就判断资源是否是调用者所在的事件锁定的,如果不是也抛出一个异常,表示该资源并非由其锁定,最后该资源所对应的信号量被置位,并且该资源从resource属性中被移除
[2020-08-01 11:20:18,258][testlog]-<thread:106940>-(line:33), [INFO]: Lock device1: time: August 01, 20 11:20:18
[2020-08-01 11:20:18,258][testlog]-<thread:106940>-(line:70), [INFO]: method1 start
[2020-08-01 11:20:28,271][testlog]-<thread:106940>-(line:46), [INFO]: Release lock for device1
[2020-08-01 11:20:28,271][testlog]-<thread:106940>-(line:73), [INFO]: method1 stop
[2020-08-01 11:20:28,271][testlog]-<thread:163360>-(line:33), [INFO]: Lock device1: time: August 01, 20 11:20:28
[2020-08-01 11:20:28,271][testlog]-<thread:163360>-(line:78), [INFO]: method2 start
[2020-08-01 11:20:38,280][testlog]-<thread:163360>-(line:46), [INFO]: Release lock for device1
[2020-08-01 11:20:38,280][testlog]-<thread:163360>-(line:81), [INFO]: method2 stop

猜你喜欢

转载自blog.csdn.net/dawei_yang000000/article/details/107727639
今日推荐