一、引入:

在无线程隔离情况下,通过线程调用函数,函数内部改变传入对象的属性值(排除非线程安全情况),都将更改传入的对象属性

 1 import threading
2
3 class TestThread:
4 value = 1
5
6 s = TestThread()
7
8 def test1():
9 s.value = 2
10
11 thread = threading.Thread(target=test1)
12 thread.start()
13
14 print(s.value)
15
16 # 2

二、Local对象

1. 使用线程隔离的意义:使当前线程能够正确引用到它自己创建的对象,而不是引用到其他线程所创建的对象。
2. 在利用flask进行WEB开发中,一定有多个请求进入服务器,那如果只实例化一个request对象并指向多个请求,那就无法获得其中任何一个请求信息。因此,flask采用线程隔离栈LocalStack对象来进行线程隔离。
3. 了解LocalStack就需要先了解Local对象。简单来说,这个Local对象内部通过字典的形式,将每个线程的id作为key,请求对象信息作为value。这样,由于每个线程id号不同,自然也就可以拿到每个线程的请求信息。以下是使用Local类做的小测试:

 1 import threading
2 from werkzeug.local import Local
3
4 s = Local()
5 s.value = 1
6
7 def test1():
8 s.value = 2
9 print("新线程的value: %d" % s.value)
10
11 thread = threading.Thread(target=test1)
12 thread.start()
13
14 print("主线程中的value: %d" % s.value)
15
16 # 新线程的value: 2
17 # 主线程中的value: 1

三、Flask中的线程隔离栈

Local使用字典的方式实现线程隔离,LocalStack封装Local对象实现了线程隔离的栈结构。这两者在使用上的区别是:使用Local对象时,可以直接像面向对象取属性一样操作,LocalStack需要进行top操作取栈顶元素(因为它毕竟是一个栈),下面是LocalStack部分源码,可以看到它内部实现了栈的一些基本操作

 1 class LocalStack:
2 """This class works similar to a :class:`Local` but keeps a stack
3 of objects instead. This is best explained with an example::
4
5 >>> ls = LocalStack()
6 >>> ls.push(42)
7 >>> ls.top
8 42
9 >>> ls.push(23)
10 >>> ls.top
11 23
12 >>> ls.pop()
13 23
14 >>> ls.top
15 42
16
17 They can be force released by using a :class:`LocalManager` or with
18 the :func:`release_local` function but the correct way is to pop the
19 item from the stack after using. When the stack is empty it will
20 no longer be bound to the current context (and as such released).
21
22 By calling the stack without arguments it returns a proxy that resolves to
23 the topmost item on the stack.
24
25 .. versionadded:: 0.6.1
26 """
27
28 def __init__(self) -> None:
29 self._local = Local()
30
31 def __release_local__(self) -> None:
32 self._local.__release_local__()
33
34 def __call__(self) -> "LocalProxy":
35 def _lookup() -> t.Any:
36 rv = self.top
37 if rv is None:
38 raise RuntimeError("object unbound")
39 return rv
40
41 return LocalProxy(_lookup)
42
43 def push(self, obj: t.Any) -> t.List[t.Any]:
44 """Pushes a new item to the stack"""
45 rv = getattr(self._local, "stack", []).copy()
46 rv.append(obj)
47 self._local.stack = rv
48 return rv
49
50 def pop(self) -> t.Any:
51 """Removes the topmost item from the stack, will return the
52 old value or `None` if the stack was already empty.
53 """
54 stack = getattr(self._local, "stack", None)
55 if stack is None:
56 return None
57 elif len(stack) == 1:
58 release_local(self._local)
59 return stack[-1]
60 else:
61 return stack.pop()
62
63 @property
64 def top(self) -> t.Any:
65 """The topmost item on the stack. If the stack is empty,
66 `None` is returned.
67 """
68 try:
69 return self._local.stack[-1]
70 except (AttributeError, IndexError):
71 return None

那么也可以手动调用LocalStack加深印象:

 1 import threading
2 from werkzeug.local import LocalStack
3
4 stack = LocalStack()
5 stack.push(1)
6 print("新线程push前,主线程的栈顶: %d" % stack.top)
7
8 def test():
9 print("新线程的栈顶: %s" % stack.top)
10 stack.push(2)
11 print("新线程push后新线程中的栈顶: %d" % stack.top)
12
13 thread = threading.Thread(target=test)
14 thread.start()
15
16 print("最终主线程的栈顶: %d" % stack.top)
17
18 # 新线程push前,主线程的栈顶: 1
19 # 新线程的栈顶: None
20 # 新线程push后新线程中的栈顶: 2
21 # 最终主线程的栈顶: 1

由此可见,每创建一个线程,该线程都会有自己的一个LocalStack来实现线程隔离

四、flask中的app和request

我们知道,flask中存在两个上下文对象(AppContext和RequestContext),flask核心对象app存放在AppContext中,请求信息Request存放在RequestContext中,那么既然Request是被线程隔离的对象(因为每次请求都需要保存当前线程的信息),app是否是被线程隔离的对象呢?
答案是否定的,核心对象app是在flask程序主入口文件创建的,也就是只有第一次请求服务器开启,会创建一个app,之后的请求都不会进入主入口文件,那么app也就不会重复创建,所以如果将app也进行线程隔离,这么做也没有太大意义。

flask中的线程隔离技术的更多相关文章

  1. Hystrix线程隔离技术解析-线程池(转)

    认识Hystrix Hystrix是Netflix开源的一款容错框架,包含常用的容错方法:线程隔离.信号量隔离.降级策略.熔断技术. 在高并发访问下,系统所依赖的服务的稳定性对系统的影响非常大,依赖有 ...

  2. flask LOCAL线程隔离技术

    from threading import Thread from werkzeug.local import Local local = Local()#实例化一个线程隔离对象 request = ...

  3. 六十九:flask上下文之线程隔离的g对象的使用

    保存全局对象的g对象g对象是在整个flask应用运行期间都是可以使用的,并且也是和request一样,是线程隔离的,这个对象是专门用来存放开发者自己定义的一些数据,方便在整个flask程序中都可以使用 ...

  4. 详解Spring Cloud中Hystrix 线程隔离导致ThreadLocal数据丢失

    在Spring Cloud中我们用Hystrix来实现断路器,Zuul中默认是用信号量(Hystrix默认是线程)来进行隔离的,我们可以通过配置使用线程方式隔离. 在使用线程隔离的时候,有个问题是必须 ...

  5. unix中的线程池技术详解

    •线程池就是有一堆已经创建好了的线程,当有新的任务需要处理的时候,就从这个池子里面取一个空闲等待的线程来处理该任务,当处理完成了就再次把该线程放回池中,以供后面的任务使用,当池子里的线程全都处理忙碌状 ...

  6. 浅谈Flask 中的 线程局部变量 request 原理

    2017-11-27 17:25:11 晚橙 阅读数 600更多 分类专栏: Flask python 多线程   版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出 ...

  7. Spring Cloud中Hystrix 线程隔离导致ThreadLocal数据丢失问题分析

    最近spring boot项目中由于使用了spring cloud 的hystrix 导致了threadLocal中数据丢失,其实具体也没有使用hystrix,但是显示的把他打开了,导致了此问题. 导 ...

  8. Flask中current_app和g对象

      Flask零基础到项目实战(七)请求方法.g对象和钩子函数 一.get方法 二.post方法 post请求在模板中要注意几点: input标签中,要写name来标识这个value的key,方便后台 ...

  9. flask高级编程 LocalStack 线程隔离

    转:https://www.cnblogs.com/wangmingtao/p/9372611.html   30.LocalStack作为线程隔离对象的意义 30.1 数据结构 限制了某些能力 30 ...

  10. 六十七:flask上下文之Local线程隔离对象

    Local对象在flask中,类似于request对象,其实是绑定到了werkzeug.local.Local对象上,这样即使是同一个对象,在多线程中都是隔离的,类似的对象还有session以及g对象 ...

随机推荐

  1. 基础文之-----typeof 和 instanceof

    为了巩固基础,我会通过实例来详细说明,让我们一起搞懂 typeof 和 instanceof. <!DOCTYPE html> <html lang="en"&g ...

  2. SSM进行Query

    在查询之前,需要输入数据库字段的名称,s_id需要获取

  3. drf基础:1、web应用模式、API接口、接口测试工具

    drf入门 一.web应用模式 ​ web的应用模式共分为两种,前后端不分离.前后端分离 1.前后端混合 ​ 之前所写的bbs项目就是前后端不分离,后端人员在开发过程中使用模板语法,前后端都由一个人员 ...

  4. Lock锁-线程状态概述

    Lock锁 java.util.concurrent.locks.Lock机制提供了比synchronized代码块和synchronized方法更广泛的锁定操作,同步代码块/同步方法具有的功能Loc ...

  5. 【OpenWRT】增加第三方开源库 - 二维码开源库 zbar

    序言 第一次开始写博客,在日常学习和工作当中 CSDN 给我帮助很大,因此我也在 CSDN 奉献自己的经验,借此回馈 CSDN 对我的帮助,希望自己的经验可以帮助需要的人,也方便自己后续复习之用,同时 ...

  6. 编程哲学之 C# 篇:006——什么是 .NET

    本章将用本系列第二章中提到的 类比 思维来让读者快速了解什么是.NET. 当年在网上看到一个初学者问<Java编程思想>第一章看不懂怎么办.然后我发现在很多经典的技术书中,如<C#入 ...

  7. JAVA虚拟机06-垃圾回收及引用类型

    Java和C++之间有一堵由内存自动分配和垃圾收集技术围成的高墙 1.了解垃圾收集.内存自动分配的意义 2.JAVA虚拟机各个区域的垃圾回收简介 3.判断对象是否存活 3.1引用计数算法 3.2可达性 ...

  8. 懂九转大肠的微软New Bing 内测申请教程

    最近微软的New Bing开放内测了,网上已经有拿到内测资格的大佬们对比了ChatGPT和New Bing.对比结果是New Bing比ChatGPT更强大.来看看具体对比例子吧 1.时效性更强 Ch ...

  9. 部署Kubernetes v1.22.10高可用集群

    一.概述 Kubernetes集群控制平面(Master)节点右数据库服务(Etcd)+其它服务组件(Apiserver.Controller-manager.Scheduler等)组成:整个集群系统 ...

  10. 通过 Blob 创建下载文件

    Blob 如上图所示,Blob 对象有三个部分组成,data:image/jpeg 表示该 Blob 是什么类型的文件.base64 是一个二进制到文本的编码,更多细节查看Base64 编码/解码.其 ...