11. 线程本地变量ThreadLocal的使用

news2024/9/22 15:42:23

1. 对ThreadLocal的理解

ThreadLocal,有人称它为线程本地变量,也有人称它为线程本地存储,其实表达的意思是一样的。ThreadLocal在每一个变量中都会创建一个副本,每个线程都可以访问自己内部的副本变量
在多线程环境下,每个线程都有自己的数据。一个线程使用自己的局部变量比使用全局变量好,因为局部变量只有线程自己能看见,不会影响其他线程,而全局变量的修改必须加锁。

2. 为什么会出现ThreadLoal这种技术应用

  我们知道多线程环境下,每一个线程均可以使用所属进程的全局变量。如果一个线程对全局变量进行了修改,将会影响到其他所有的线程对全局变量的计算操作,从而出现数据混乱,称之为脏数据。为了避免多个线程同时对变量进行修改,引入了线程同步进制,通过互斥锁、条件变量、信号量或读写锁这种手段来控制对全局变量的访问。
  只用全局变量并不能满足多线程环境的需求,很多时候线程还需要拥有自己的私有数据,这些数据对于其他线程来说是不可见的。因此线程中也可以使用局部变量,局部变量只有线程自身可以访问,同一个进程下的其他线程不可访问。
  有时候使用局部变量很不方便,为此python中提供了ThreadLocal变量,它本身是一个全局变量,但是每个线程却可以利用它来保存属于自己的私有数据,这些私有数据对其他线程也是不可见的
  ThreadLocal真正的做到了线程之间的数据隔离

  ThreadLocal最常用的地方就是为每个线程绑定一个数据库连接,HTTP请求,用户身份信息等,这样一个线程的所有调用到的处理函数都可以非常方便地访问这些资源。

3. ThreadLocal的雏形

# demo
# 我们开启2个线程, 分别是线程1和线程2, 并且每个线程携带一个Student对象,
# 当执行线程函数的时候, 将线程名与线程参数(Student对象)依据线程名存储在g_dict中,
# 然后通过线程名来执行不同的操作do_1()和do_2(),
# 注意在do_1()和do_2()中我们并没有传入参数, 而是根据线程名去寻找与之绑定的数据,
# 这样一样, 确实在不同的线程之中起到了保存各自数据的一种效果.
import threading

g_dict = {}


class Student:
    def __init__(self, num, name):
        self.num = num
        self.name = name

    def __str__(self):
        return '{0}:{1}'.format(self.num, self.name)


def do_1():
    s = g_dict[threading.current_thread().name]
    print('%s in %s' % (s, threading.current_thread().name))


def do_2():
    s = g_dict[threading.current_thread().name]
    print('%s in %s' % (s, threading.current_thread().name))


def MyThread(student):
    g_dict[threading.current_thread().name] = student
    if threading.current_thread().name == 'thread_1':
        do_1()
    elif threading.current_thread().name == 'thread_2':
        do_2()
    else:
        pass


t1 = threading.Thread(target=MyThread, args=(Student(101, 'Zhang'),), name="thread_1")
t2 = threading.Thread(target=MyThread, args=(Student(102, 'Wang'),), name="thread_2")

t1.start()
t2.start()
t1.join()
t2.join()

在这里插入图片描述

4. ThreadLocal的初步使用

import threading

# 创建全局的线程本地变量
local_var = threading.local()


class Student:
    def __init__(self, num, name):
        self.num = num
        self.name = name

    def __str__(self):
        return '{0}:{1}'.format(self.num, self.name)


class Score:
    def __init__(self, score):
        self.score = score

    def __str__(self):
        return '{0}'.format(self.score)


def do():
    stu = local_var.student  # 获取当前线程关联的Student对象
    sco = local_var.score  # 获取当前线程关联的Score对象
    print('%s is %s in [%s]' % (stu, sco, threading.current_thread().name))


# 将stu和sco变量存储在local_var下去,
# 可以这么理解, 当线程1执行时, 将local_var进行了一份拷贝, 然后将线程1相关的数据保存在其中,
# 线程2亦是如此...
# 当执行do()时, local_var会自动根据当前线程拿出与其所绑定的数据...
def MyThread(stu, sco):
    local_var.student = stu
    local_var.score = sco
    do()


t1 = threading.Thread(target=MyThread, args=(Student(101, 'Zhang'), Score(100)), name="thread_1")
t2 = threading.Thread(target=MyThread, args=(Student(102, 'Wang'), Score(98)), name="thread_2")

t1.start()
t2.start()
t1.join()
t2.join()

在这里插入图片描述
全局变量local_var就是一个ThreadLocal对象,每个Thread对它都可以读写student属性和score属性且互不影响。你可以把local_var看成全局变量,但每个属性如local_var.student,local_var.score都是线程的局部变量,可以任意读写而互不干扰,也不用管理锁的问题,ThreadLocal内部会处理

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/182055.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

tomcat 的并发能力分析

tomcat 参考:Tomcat的3个参数acceptCount、maxConnections、maxThreads Tomcat 的核心组件 Tomcat 由 2 大核心组件组成:Connector、Container Tomcat 处理请求的过程 请求在 tomcat 服务器的处理过程(BIO 模式) 客户端与服务…

嵌入式串行通信协议

嵌入式系统中,不同芯片之间通常使用串行总线的方式进行连接,根据器件行业规范、应用场景,不同芯片通常选择不同的串行通信接口进行通信。常用的串行通信接口有:1-Wire、I2C、SPI、UART。 一、1-Wire 1-wire单总线是Maxim的全资子…

bodgeito通关教程

6.bodgeito通关教程 进入网站整体浏览网页 点击页面评分进入关卡 一般搭建之后这里都是红色的&#xff0c;黄色是代表接近&#xff0c;绿色代表过关 首先来到搜索处本着见框就插的原则 构造payload输入 <script> alert(/xss/)</script>成功弹窗xss&#xff0c;发…

Redis数据库

1.Redis简介 1.1Redis简介 Redis 是当前互联网世界最为流行的 NoSQL&#xff08;Not Only SQL&#xff09;数据库。NoSQL 在互联网系统中的作用很大&#xff0c;因为它可以在很大程度上提高互联网系统的性能。 Redis 具备一定持久层的功能&#xff0c;也可以作为一种缓存工具…

c++实现堆排序

看了一下优先队列&#xff0c;查了一下堆排序。堆排序主要就是建最大堆&#xff08;最小堆&#xff09;和交换2个操作。如果建的是最大堆&#xff0c;那么交换的时候&#xff0c;父节点就和最大的子节点比较&#xff0c;如果它比最大的子节点还大&#xff0c;那就不用比了。因为…

STM32MP157开发板Linux+Qt项目实战:智能猫眼

stm32mp157开发板FS-MP1A是华清远见自主研发的一款高品质、高性价比的Linux单片机二合一的嵌入式教学级开发板。开发板搭载ST的STM32MP157高性能微处理器&#xff0c;集成2Cortex-A7核和1个Cortex-M4 核&#xff0c;A7核上可以跑Linux操作系统&#xff0c;M4核上可以跑FreeRTOS…

docker 搭建postgres 主从 pgadmin

准备工作 创建一个docker bridge 网路用于测试 docker network create -d bridge --subnet 192.168.0.0/24 --gateway 192.168.0.1 pgnetwork # 查看 docker network ls 设置了网段为 192.168.0.0&#xff0c;规划主从库IP端口如下&#xff1a; 主库 192.168.0.101:5432 从库…

Ubuntu16.04安装深度学习环境(CUDA9.2+PyTorch0.4.1+Python2.7)

之前已经安装好了显卡驱动&#xff0c;接着就可以安装CUDA了于是又找了好几篇文章进行参考&#xff1a;https://zhuanlan.zhihu.com/p/361190040https://blog.csdn.net/qq_43665602/article/details/125752433https://blog.csdn.net/myg22/article/details/84029924https://blo…

二、数据缓存

文章目录数据缓存1.标准缓存流程2.缓存更新一致性3.缓存穿透解决方案缓存空对象布隆过滤器4.缓存雪崩解决方案5.缓存击穿解决方案互斥锁逻辑过期6.使用函数式接口封装工具类学习 黑马点评项目整理总结: https://www.bilibili.com/video/BV1cr4y1671t/?vd_source5f3396d3af2c39…

webpack项目配置

30.webpack——webpack5新特性&#xff08;启动、持久化缓存、资源模块、URIs、moduleIds和chunkIds、tree shaking、nodeJs的polyfill被移除、模块联邦&#xff09;_俞华的博客-CSDN博客_chunkids webpack和vite的区别 - 简书 vite介绍 &#xff5c; 与其他构建工具做比较&…

【ONE·C || 字符串和内存函数】

总言 C语言&#xff1a;字符串和内存函数使用介绍。 文章目录总言1、求字符串长度&#xff1a;strlen1.1、基本介绍1.2、演示说明1.2.1、strlen输出1.2.2、strlen返回值1.3、模拟实现strlen1.3.1、计数器写法1.3.2、递归写法1.3.3、指针-指针写法2、长度不受限制的字符串函数2.…

educoder数据结构 图 无错AC代码版

目录 第1关&#xff1a;实现图的宽度优先遍历 任务描述 相关知识 编程要求 测试说明 输入输出格式说明&#xff1a; 样例输出 Ac_Code 第2关&#xff1a;实现图的深度优先遍历 任务描述 相关知识 测试说明 输入输出格式&#xff1a; 样例输出 AC_Code 第1关&am…

2023年flag

开头总是让人那么茫然无措&#xff0c;在这里记录梳理上一年。以期找到前进的方向&#xff0c;迈开新一年的第一步&#xff0c;然后不断前行。 回顾上一年 首先想到的第一件事&#xff0c;11月换了个工作依然是Java开发10月份准备了软件工程中级考试并考过读了几本技术的书籍…

【设计模式】我终于读懂了享元模式。。。

祝大家开工大吉&#x1f9e7;&#x1f9e7;&#x1f9e7;&#xff01;&#xff01;主页有红包哦 点这里 文章目录祝大家开工大吉&#x1f9e7;&#x1f9e7;&#x1f9e7;&#xff01;&#xff01;主页有红包哦 [点这里](https://blink.csdn.net/details/1469531)&#x1f9e7;…

Python基础学习 -- 进程锁

一、join函数的作用1、等子进程执行完&#xff0c;主进程再结束2、将子进程都存储到一个列表&#xff0c;每个子进程都调用一下join方法if __name__"__main__":print("我是主线程")stime.time()a[2,3,4]b[] #存储创建好的进程for i in a:pProcess(targetfu…

入门算法,这篇文章你得看!(java、算法基础、常用算法)

想用Java快速入门算法&#xff1f;这篇文章你得看&#xff01; 提示&#xff1a;本文章适合想要入门算法&#xff0c;并且想 “快速” 达到一定成果的同学们阅读~ 文章非常非常非常长&#xff08;可能是你见过最长的博客&#xff09;&#xff01;&#xff01;&#xff01; 阅读…

Authing 身份云入选《数字身份治理与管理(IGA)应用实践指南》报告

身份是物理实体映射在网络空间的一串数字代码&#xff0c;是数字世界的通行证。掌控了统一的权威数字身份就等同掌控了实体在数字空间的行为。网络业务的快速发展&#xff0c;使业务与安全深度融合到一起&#xff0c;并使数字身份成为数字化经济建设的重要基石。同一实体可以更…

【数据结构初阶】第一篇——算法性能分析

算法效率 什么是大O 时间复杂度分析 概念 大O渐进表示法 不同数据规模的差异 复杂表达式的化简 O(logn)中的log是以什么为底? 案例分析 算法为什么会超时 递归算法的时间复杂度 空间复杂度分析 概念 案例分析 递归算法的性能分析 代码的内存消耗 算法效率 算法…

如何使用VMware虚拟机(带你快速了解)

前言 &#x1f4dc; “作者 久绊A” 专注记录自己所整理的Java、web、sql等&#xff0c;IT技术干货、学习经验、面试资料、刷题记录&#xff0c;以及遇到的问题和解决方案&#xff0c;记录自己成长的点滴 目录 前言 一、什么是虚拟机 二、VMware的简介 1、大概介绍 2、详…

数据结构 第四章 串

她&#xff1a;点击收听 1 基本知识点 1、串中的元素是字符 2、操作的对象往往不再是单个数据元素,而是一组数据元素(子串) 3、串&#xff1a;由零个或多个字符组成的有限序列 4、子串&#xff1a;串中任意连续个字符组成的子序列 5、包含子串的串又被称为该子串的主串 6、真…