MST

星途 面试题库

面试题:Python多线程异常处理与线程同步机制的协同

在一个多线程Python应用中,多个线程共享一个数据库连接池资源。当某个线程在使用连接执行数据库操作抛出异常时,如何在处理异常的同时,保证连接池的状态正确且不影响其他线程对连接池的正常使用,并且避免死锁情况的发生?请详细阐述设计思路并给出关键代码片段。
31.4万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 异常处理:当线程在使用连接执行数据库操作抛出异常时,捕获异常进行处理。
  2. 连接池状态维护:确保异常发生后,将使用的连接正确归还到连接池,避免连接泄露。
  3. 避免死锁:使用锁机制来控制对连接池的访问,确保同一时间只有一个线程能对连接池进行关键操作(如获取和归还连接),但要注意锁的粒度,避免过度锁定导致死锁。

关键代码片段

import threading
import queue
import sqlite3


# 数据库连接池类
class ConnectionPool:
    def __init__(self, max_connections=5):
        self.max_connections = max_connections
        self.pool = queue.Queue(maxsize=max_connections)
        self.lock = threading.Lock()
        for _ in range(max_connections):
            self.pool.put(sqlite3.connect('example.db'))

    def get_connection(self):
        with self.lock:
            return self.pool.get()

    def return_connection(self, conn):
        with self.lock:
            self.pool.put(conn)


# 线程执行的函数
def worker(pool):
    conn = None
    try:
        conn = pool.get_connection()
        cursor = conn.cursor()
        cursor.execute('SELECT * FROM some_table')
        result = cursor.fetchall()
        print(result)
    except sqlite3.Error as e:
        print(f"发生数据库异常: {e}")
    finally:
        if conn:
            pool.return_connection(conn)


# 创建连接池实例
pool = ConnectionPool()

# 创建并启动多个线程
threads = []
for _ in range(3):
    t = threading.Thread(target=worker, args=(pool,))
    threads.append(t)
    t.start()

# 等待所有线程完成
for t in threads:
    t.join()

在上述代码中:

  • ConnectionPool 类实现了数据库连接池,使用 queue.Queue 来管理连接,threading.Lock 来控制对连接池的访问。
  • worker 函数模拟线程执行数据库操作,在 try 块中获取连接执行操作,在 except 块中捕获数据库异常,在 finally 块中确保连接归还到连接池。
  • 主线程创建连接池实例,并启动多个线程执行 worker 函数。这样在异常发生时,能保证连接池状态正确且避免死锁,不影响其他线程对连接池的正常使用。