zoukankan      html  css  js  c++  java
  • flask线程隔离技术

    1
    多个线程操作同一对象带来的问题

     

    多个线程修改同一对象属性,会造成数据错乱。

     

    import timeimport threading

    class A: b = 1

    obj1 = A()

    def worker(): obj1.b = 2

    t1 = threading.Thread(target=worker)t1.start()time.sleep(1)print(obj1.b)

     

    输出结果:

     

    2

     

    2

    如何做到线程隔离?

     

    """Local是被线程隔离的对象"""import timeimport threadingfrom werkzeug.local import Local

    obj1 = Local()obj1.b = 1

    def worker(): obj1.b = 2 print("子线程中obj1.b的值为{}".format(obj1.b))

    t1 = threading.Thread(target=worker)t1.start()time.sleep(1)print("主线程中obj1.b的值为{}".format(obj1.b))

     

    输出结果:

     

    子线程中obj1.b的值为2主线程中obj1.b的值为1

     

    所以,凡是继承了Local的,都是线程隔离的

     

    3
    Local实现线程隔离的方法

     

    阅读源码文件,local.py

     

    def __setattr__(self, name, value): ident = self.__ident_func__() # 取当前线程的线程ID号 storage = self.__storage__# 操作字典,把线程id号作为key保存起来try: storage[ident][name] = value except KeyError: storage[ident] = {name: value}

     

    原来,Local是通过字典这种python中的数据结构实现的线程隔离。每一个线程都有对应的自己的线程ID, 并将对象作为value存放。如:{线程ID1:对象, 线程ID2:对象}

     

    4

    flask的线程隔离栈 LocalStack

     

    阅读flask源码文件globals.py文件

    # context locals_request_ctx_stack = LocalStack()_app_ctx_stack = LocalStack()current_app = LocalProxy(_find_app)request = LocalProxy(partial(_lookup_req_object, 'request'))session = LocalProxy(partial(_lookup_req_object, 'session'))g = LocalProxy(partial(_lookup_app_object, 'g'))

     

    发现请求上下文(_request_ctx_stack) 和 应用上下文 (_app_ctx_stack) 都是LocalStack类的对象。LocalStack这个单词可以分为Local和Stack两个部分,顾名思义LocalStack:是封装Local实现线程隔离的栈结构。如下代码可以验证LocalStack是一个线程隔离的栈结构:

     

    # LcoalStack线程隔离的栈import timeimport threadingfrom werkzeug.local import LocalStackmy_stack = LocalStack()my_stack.push(1)print("主线程中,栈顶元素为{}".format(str(my_stack.top)))def worker(): print("在push之前,子线程中的栈顶元素为{}".format(str(my_stack.top))) my_stack.push(2) print("在push之后,子线程中的栈顶元素为{}".format(str(my_stack.top)))t1 = threading.Thread(target=worker)t1.start()time.sleep(1)print("最后,主线程中的栈顶元素为{}".format(str(my_stack.top)))

     

    输出结果:

     

    主线程中,栈顶元素为1在push之前,子线程中的栈顶元素为None在push之后,子线程中的栈顶元素为2最后,主线程中的栈顶元素为1

     

    5
    flask线程隔离技术

     

    由之前写过的文章得知current_app、request、session、g等对应都是指向相应栈的栈顶,当我们接受到一个请求里,flask才会把相应的app对象和新创建的Request对象压入相应的栈。由此,我们就知道了flask是怎么实现的多个请求,request的线程隔离。最后总结一下,字典、Local、LocalStack三者的关系,Local使用字典的方式实现的线程隔离,LocalStack封装了Local对象,并把它作为了自己的一个属性,从而实现了线程隔离的栈结构

     

     
  • 相关阅读:
    从头编写 asp.net core 2.0 web api 基础框架 (1)
    希腊字母表
    Python数据分析(二): Numpy技巧 (4/4)
    Python数据分析(二): Numpy技巧 (3/4)
    Python数据分析(二): Numpy技巧 (2/4)
    OLED液晶屏幕(3)串口读取文字并分割
    OLED液晶屏幕(2)取模软件
    OLED液晶屏幕(0)自动获取12ic地址液晶屏幕
    OLED液晶屏幕(1)OLED液晶屏幕ssd1306驱动芯片 arduino运行 ESP8266-07可以 12f不可以
    I2C 连接 12864 OLED 屏幕
  • 原文地址:https://www.cnblogs.com/lirunsheng/p/10838947.html
Copyright © 2011-2022 走看看