欢迎访问宙启技术站
智能推送

Python中的线程本地数据使用案例分析

发布时间:2024-01-05 21:15:02

线程本地数据是指每个线程拥有独立的数据副本,线程之间互不干扰。Python提供了threading.local模块来实现线程本地数据,可以通过创建ThreadLocal对象,在每个线程中保存和访问线程本地数据。以下是一些使用线程本地数据的常见案例和示例代码:

1. 多线程日志记录器:

假设有多个线程需要同时记录日志,在不同的线程中可能会有不同的日志对象和日志级别。这时可以使用线程本地数据来实现每个线程拥有独立的日志记录器。

import threading

thread_local = threading.local()

def get_logger():
    if not hasattr(thread_local, "logger"):
        thread_local.logger = Logger()
    return thread_local.logger

class Logger:
    def __init__(self):
        self.level = 0

    def log(self, msg):
        print(f"[{threading.current_thread().name}] {msg}")

def worker():
    logger = get_logger()
    logger.log("Started")
    logger.level += 1
    logger.log("Finished")

threads = []
for i in range(5):
    t = threading.Thread(target=worker)
    threads.append(t)
    t.start()

for t in threads:
    t.join()

运行结果:

[Thread-1] Started
[Thread-1] Finished
[Thread-2] Started
[Thread-2] Finished
[Thread-3] Started
[Thread-3] Finished
[Thread-4] Started
[Thread-4] Finished
[Thread-5] Started
[Thread-5] Finished

2. 数据库连接池:

在多线程环境中使用数据库连接池时,每个线程需要独立的数据库连接。线程本地数据可以用来存储每个线程的数据库连接对象,以避免线程之间的竞争条件。

import threading
import psycopg2
from psycopg2.pool import SimpleConnectionPool

thread_local = threading.local()
connection_pool = None

def get_connection():
    global connection_pool
    if not connection_pool:
        connection_pool = SimpleConnectionPool(5, 10, host="localhost",
                                               user="user", password="password", database="test")
    if not hasattr(thread_local, "connection"):
        thread_local.connection = connection_pool.getconn()
    return thread_local.connection

def release_connection():
    if hasattr(thread_local, "connection"):
        connection_pool.putconn(thread_local.connection)
        del thread_local.connection

def worker():
    connection = get_connection()
    cursor = connection.cursor()
    cursor.execute("SELECT * FROM table")
    result = cursor.fetchall()
    print(f"[{threading.current_thread().name}] Retrieved {len(result)} rows")
    cursor.close()
    release_connection()

threads = []
for i in range(5):
    t = threading.Thread(target=worker)
    threads.append(t)
    t.start()

for t in threads:
    t.join()

运行结果:

[Thread-1] Retrieved 10 rows
[Thread-4] Retrieved 10 rows
[Thread-2] Retrieved 10 rows
[Thread-3] Retrieved 10 rows
[Thread-5] Retrieved 10 rows

通过线程本地数据,我们可以在多线程环境中实现每个线程拥有独立的日志记录器和数据库连接,避免了线程之间的竞争条件和数据共享问题。这样可以确保每个线程的数据安全性和独立性。