Python threading Local()函数用法:返回线程局部变量

Python threading Local()函数用法:返回线程局部变量

一、使用场景

当多线程操作同一个公共资源时,如果涉及到该资源的修改,比如:对同一个文件进行读写操作,多同一个数组进行增加删除等等,为了避免数据不同步可能导致的错误,需要使用互斥锁机制。

其实,除非必须将多线程使用的资源设置为公共资源,Python threading还提供了一种可彻底避免数据不同步问题的方法。即local()函数。

使用local()函数创建的变量,可以被各个线程调用,但和公共资源不同,各个线程在使用local()函数创建的变量时,都会在该线程自己的内存空间中拷贝一份。这意味着,local()函数创建的变量看似是全局变量(可以被各个线程调用),但各个线程调用的都是该变量的副本(各自调用各自的,彼此之间并无关系)。

可以这么理解,使用threading模块中的local()函数,可以为各个线程创建完全属于它们自己的变量(又称线程局部变量)。正是由于各个线程操作的是属于自己的变量,该资源属于各个线程的私有资源,因此可以从根本上杜绝发生数据同步问题。

示例代码如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import threading

# 创建全局ThreadLocal对象:
local = threading.local()

def process():
    # 3.获取当前线程关联的resource:
    res = local.resource
    print (res + "http://c.biancheng.net/python/")

def process_thread(res):
    # 1.为当前线程绑定ThreadLocal的resource:
    local.resource = res
    # 2.线程的调用函数不需要传递res了,可以通过全局变量local访问
    process()

t1 = threading.Thread(target=process_thread, args=('t1线程',))
t2 = threading.Thread(target=process_thread, args=('t2线程',))
t1.start()
t2.start()

程序执行结果为:

t1线程http://c.biancheng.net/python/
t2线程http://c.biancheng.net/python/

二、样例分析

分析如下:

  1. 首先,在全局作用域范围内,调用local()函数会生成一个ThreadLocal对象,由此生成的local变量即为公共资源,它可以在程序的任意线程中被调用。

  2. 随后,创建了两个线程t1和t2,它们都负责执行process_thread()函数,该函数中,我们在全局local变量的基础上,定义了一个resource变量,该变量即为线程局部变量,即哪个线程调用该函数,都会将resource变量拷贝一份并存储在自己的存储空间中,因此,t1和t2线程会各自拥有一份resource变量的副本。

    注意:虽然变量名相同,但是值不同,t1线程传递的res参数为“t1线程”,而t2线程传递的res参数值为“t2线程”

  3. 但是各个线程拷贝resource变量完成后,随即执行process()函数,在该函数中,我们可以使用ThreadLocal类型的local全局变量,调用各个线程自己的resource变量。

    需要说明的一点是,该程序中,只用ThreadLocal类型的对象local创建了一个resource变量,根据实际场景需要,我们完全可以创建任意个线程局部变量。

    通过上面样例的分析,使用local()的好处,至少有以下两点:

    1、各个线程操作的都是自己的私有资源,不会涉及到数据同步问题

    2、由于local()函数的返回值位于全局作用域,无论在程序什么位置,都可以随时调用,很方便。

三、总结

无论是使用线程局部变量,还是使用互斥锁机制,其根本目的是为了解决多线程访问公共资源时可能发生的数据同步问题。互斥锁机制实现的出发点是,在各线程仍使用公共资源的前提下,想办法控制各个线程对该资源的同时访问;而线程局部变量则另辟蹊径,直接令多线程操作各自的私有资源,从根本上杜绝了同时访问所带来的数据同步问题。

需要说明的一点是,线程局部变量的解决方案,并不能完全替代互斥锁同步机制。同步机制是为了同步多个线程对公共资源的并发访问,是多个线程之间进行通信的有效方式;而线程局部变量则从根本上避免了多个线程之间对共享资源(变量)的竞争。

那么,这两种解决方案该如何选择呢?简单来说,如果多线程之间需要共享资源(如多人操作同一银行账户的例子),就使用互斥锁机制;反之,如果仅仅是为了解决多线程之间共享资源冲突,则推荐使用线程局部变量。

四、原文链接

http://c.biancheng.net/view/2628.html

说明:该网站啥都有,只要你想学,这里都有你要的。

原文地址:https://www.cnblogs.com/huaibin/p/15008490.html