MST

星途 面试题库

面试题:网络编程之非阻塞I/O模型下的线程安全挑战

假设在非阻塞I/O的网络编程场景中,多个线程同时访问和修改共享的连接池资源,可能会出现哪些线程安全问题?请列举至少两种,并说明如何解决这些问题。
45.6万 热度难度
后端开发网络编程

知识考点

AI 面试

面试题答案

一键面试

可能出现的线程安全问题:

  1. 资源竞争:多个线程同时尝试从连接池中获取或释放连接,导致连接状态不一致或连接丢失。例如,一个线程刚获取到连接准备使用,另一个线程却同时将该连接从连接池中移除,使得第一个线程使用的连接处于非法状态。
  2. 数据不一致:线程对连接池的元数据(如连接数量、活跃连接数等)进行并发修改时,可能导致数据不一致。比如,一个线程增加连接数量计数,另一个线程同时减少计数,由于操作不是原子性的,可能导致最终计数错误。

解决方法:

  1. 互斥锁(Mutex):使用互斥锁来保护连接池的关键部分。在获取或释放连接以及修改连接池元数据时,先获取互斥锁,操作完成后释放互斥锁。这样可以确保同一时间只有一个线程能访问和修改连接池资源。例如在Python中,可以使用threading.Lock
import threading

class ConnectionPool:
    def __init__(self):
        self.lock = threading.Lock()
        self.connections = []

    def get_connection(self):
        with self.lock:
            if self.connections:
                return self.connections.pop()
            else:
                return None

    def release_connection(self, conn):
        with self.lock:
            self.connections.append(conn)
  1. 信号量(Semaphore):信号量可以控制同时访问连接池的线程数量。设置信号量的初始值为连接池的最大连接数,每个线程获取连接前先获取信号量,释放连接后再释放信号量。这样可以避免过多线程同时竞争连接资源。以Java为例:
import java.util.concurrent.Semaphore;

public class ConnectionPool {
    private Semaphore semaphore;
    private int maxConnections;

    public ConnectionPool(int maxConnections) {
        this.maxConnections = maxConnections;
        this.semaphore = new Semaphore(maxConnections);
    }

    public void getConnection() throws InterruptedException {
        semaphore.acquire();
        // 获取连接的实际逻辑
    }

    public void releaseConnection() {
        semaphore.release();
    }
}
  1. 读写锁(Read - Write Lock):如果对连接池的操作读多写少,可以使用读写锁。读操作时允许多个线程同时进行,写操作(如添加或移除连接)则需要独占锁。在C++中可以使用std::shared_mutex实现:
#include <iostream>
#include <shared_mutex>
#include <vector>

class ConnectionPool {
public:
    std::vector<int> connections;
    std::shared_mutex mtx;

    void getConnection() {
        std::shared_lock<std::shared_mutex> lock(mtx);
        // 获取连接逻辑
    }

    void releaseConnection(int conn) {
        std::unique_lock<std::shared_mutex> lock(mtx);
        connections.push_back(conn);
    }
};