You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python线程同步问题求助:continue_program执行时需锁定其他方法

Python线程同步问题解决方案

问题分析

你的代码存在以下核心问题:

  • 定义了threading.Lock但未实际使用,导致continue_program执行时其他线程仍能继续运行
  • 共享变量self.flag的读写未加同步,存在线程可见性问题
  • socket.accept()是阻塞调用,即使self.flag被设为False,主线程会卡在该调用上无法及时退出
  • continue_program中仅处理yes/y和其他情况,但未通过锁机制阻塞其他方法

修改后的代码

import socket
import threading


class Server:
    def __init__(self, host, port):
        self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        # 设置socket超时,避免accept永久阻塞
        self.server.settimeout(1)
        self.host = host
        self.port = port
        self.flag = True
        self.locker = threading.Lock()

    def start_server(self):
        self.server.bind((self.host, self.port))
        self.server.listen(5)
        print("Created the server")

        while self.flag:
            # 尝试获取锁,只有当continue_program执行完毕释放锁后才能继续
            with self.locker:
                if not self.flag:
                    break
                print("Waiting when client connects")
                try:
                    client, _ = self.server.accept()
                except socket.timeout:
                    continue
                print("Client connected")
            # 处理客户端的线程启动时不持有锁,避免阻塞其他操作
            t = threading.Thread(target=self.handle_client, args=(client,))
            t.start()

        # 关闭服务器socket
        self.server.close()
        print("Server stopped")

    def handle_client(self, client):
        while self.flag:
            # 每次接收数据前检查锁和flag
            with self.locker:
                if not self.flag:
                    break
            try:
                data = client.recv(4096)
            except Exception as e:
                print(f"Client error: {e}")
                break
            if not data:
                print("Client disconnected")
                break
            data = data.decode("utf-8")
            print(f"Data received: \n{data}")
            # 调用continue_program时持有锁,阻塞其他需要锁的方法
            with self.locker:
                self.continue_program()
                # 执行完后检查flag,若为False则退出循环
                if not self.flag:
                    break
        client.close()

    def continue_program(self):
        con_inp = input("Continue(yes,no)?: ")
        if con_inp.lower() in ["yes", "y"]:
            return
        # 所有非yes/y的输入都设置flag为False
        self.flag = False


if __name__ == "__main__":
    obj_server = Server("127.0.0.1", 8080)
    obj_server.start_server()

关键修改说明

  1. 锁的正确使用:

    • start_server的循环中用with self.locker包裹accept操作,确保continue_program执行时主线程无法继续等待新客户端
    • handle_client调用continue_program时持有锁,此时start_server会被阻塞,直到锁被释放
    • continue_program在锁保护下修改self.flag,避免多线程竞态
  2. 解决socket阻塞问题:

    • 给服务器socket设置1秒超时,accept每隔1秒返回一次超时异常,循环中可及时检查self.flag状态并退出
  3. 线程安全的flag处理:

    • 所有对self.flag的读写都在锁的保护下,保证线程可见性和操作原子性
  4. 输入逻辑优化:

    • 无论输入no/n还是其他内容,都会将self.flag设为False,确保服务器能及时停止

内容的提问来源于stack exchange,提问作者clqwnless

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 20:57:28