MST

星途 面试题库

面试题:Python多线程性能优化之资源竞争处理

在Python多线程程序中,当多个线程同时访问和修改共享资源时,可能会出现资源竞争问题从而影响性能。请描述如何使用锁机制(如`threading.Lock`)来解决该问题,并举例说明在复杂场景下如何避免死锁。
47.3万 热度难度
编程语言Python

知识考点

AI 面试

面试题答案

一键面试

使用锁机制解决资源竞争问题

在Python多线程程序中,threading.Lock是一种常用的锁机制。当一个线程获取到锁时,其他线程必须等待该线程释放锁后才能获取并访问共享资源,从而避免资源竞争。

示例代码如下:

import threading

# 共享资源
shared_variable = 0
lock = threading.Lock()


def increment():
    global shared_variable
    for _ in range(100000):
        # 获取锁
        lock.acquire()
        try:
            shared_variable += 1
        finally:
            # 释放锁
            lock.release()


threads = []
for _ in range(10):
    t = threading.Thread(target=increment)
    threads.append(t)
    t.start()

for t in threads:
    t.join()

print(f"Final value of shared variable: {shared_variable}")

在上述代码中,每个线程在修改shared_variable之前获取锁,修改完成后释放锁,确保同一时间只有一个线程可以修改共享变量。

避免死锁的方法

在复杂场景下,死锁可能会发生,即两个或多个线程相互等待对方释放锁。以下是几种避免死锁的方法:

  1. 按顺序获取锁: 所有线程按照相同的顺序获取多个锁。例如,如果有锁lock1lock2,所有线程都先获取lock1,再获取lock2。这样可以避免循环等待的情况。

示例代码:

import threading

lock1 = threading.Lock()
lock2 = threading.Lock()


def thread1():
    lock1.acquire()
    try:
        print("Thread 1 acquired lock1")
        lock2.acquire()
        try:
            print("Thread 1 acquired lock2")
        finally:
            lock2.release()
    finally:
        lock1.release()


def thread2():
    lock1.acquire()
    try:
        print("Thread 2 acquired lock1")
        lock2.acquire()
        try:
            print("Thread 2 acquired lock2")
        finally:
            lock2.release()
    finally:
        lock1.release()


t1 = threading.Thread(target=thread1)
t2 = threading.Thread(target=thread2)
t1.start()
t2.start()
t1.join()
t2.join()

在这个例子中,两个线程都先获取lock1,再获取lock2,避免了死锁。

  1. 使用超时机制: 在获取锁时设置超时时间,如果在规定时间内没有获取到锁,则放弃获取并进行其他处理。

示例代码:

import threading
import time

lock1 = threading.Lock()
lock2 = threading.Lock()


def thread3():
    if lock1.acquire(timeout=1):
        try:
            print("Thread 3 acquired lock1")
            if lock2.acquire(timeout=1):
                try:
                    print("Thread 3 acquired lock2")
                finally:
                    lock2.release()
        finally:
            lock1.release()
    else:
        print("Thread 3 could not acquire lock1 within 1 second")


def thread4():
    if lock2.acquire(timeout=1):
        try:
            print("Thread 4 acquired lock2")
            if lock1.acquire(timeout=1):
                try:
                    print("Thread 4 acquired lock1")
                finally:
                    lock1.release()
        finally:
            lock2.release()
    else:
        print("Thread 4 could not acquire lock2 within 1 second")


t3 = threading.Thread(target=thread3)
t4 = threading.Thread(target=thread4)
t3.start()
t4.start()
t3.join()
t4.join()

此代码中,线程在获取锁时设置了1秒的超时时间,如果获取失败会打印提示信息,避免了无限等待导致死锁。

  1. 资源分配图算法: 在复杂系统中,可以使用资源分配图算法(如银行家算法)来检测和避免死锁。该算法通过跟踪系统中资源的分配情况,在分配资源前进行安全性检查,确保不会导致死锁。不过,这种方法实现起来相对复杂,通常适用于大型多线程系统。