我不是第一个 发表于 2023-9-9 22:32:00

多线程问题

多线程同时运行时,在遇到特定函数时,怎么只执行一次。
比如遇到验证码时。{:5_109:}

isdkz 发表于 2023-9-9 22:32:10

可以使用信号量(Semaphore)来解决这个问题。

信号量是一个计数器,用于控制访问特定资源的线程数量。当信号量的值为1时,只有一个线程可以访问该资源。当信号量的值为0时,所有线程都被阻塞,直到信号量的值变为1。

在遇到验证码时,可以创建一个初始值为1的信号量。当一个线程需要执行特定函数时,它会尝试获取信号量。如果信号量的值为1,则该线程可以执行特定函数并将信号量的值减1。如果信号量的值为0,则该线程将被阻塞,直到另一个线程释放信号量。

下面是一个使用信号量的示例代码:

import threading

# 创建一个初始值为1的信号量
semaphore = threading.Semaphore(1)

def do_something():
    # 尝试获取信号量
    semaphore.acquire()
   
    # 执行特定函数
    # ...

    # 释放信号量
    semaphore.release()

# 创建多个线程
threads = []
for i in range(10):
    t = threading.Thread(target=do_something)
    threads.append(t)

# 启动所有线程
for t in threads:
    t.start()

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


在上面的代码中,当多个线程同时运行时,只有一个线程可以获取信号量并执行特定函数,其他线程将被阻塞。当执行特定函数的线程释放信号量后,其他线程可以获取信号量并执行特定函数。这样就可以保证特定函数只被执行一次。

Mike_python小 发表于 2023-9-10 08:22:58

在多线程同时运行时,要想在遇到特定函数时只执行一次,可以使用同步机制来实现。以下是一种可能的解决方案:

1. 创建一个全局变量,用于标记特定函数是否已经执行。

2. 在特定函数执行前,检查该全局变量的状态。如果已经被标记为已执行,则跳过函数执行;否则,继续执行函数。

3. 在特定函数执行完成后,更新该全局变量的状态为已执行,以确保其他线程在遇到特定函数时可以跳过执行。

下面是一个示例代码片段,演示如何在多线程环境下控制特定函数的执行次数:

import threading

# 全局变量,用于标记特定函数是否已经执行
function_executed = False

# 特定函数
def special_function():
    global function_executed
    if not function_executed:
      # 执行特定操作,例如验证码的处理
      print("执行特定函数")
      function_executed = True

# 多线程任务
def worker():
    # 其他任务...

    # 在遇到特定函数时,只执行一次
    special_function()

    # 其他任务...

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

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


在上述示例中,`special_function` 函数只会在第一个线程执行时被执行一次,后续线程在遇到该函数时会跳过执行。

请注意,全局变量的访问要确保线程安全,可以使用锁机制或其他同步原语来保证多个线程对全局变量的访问操作不会冲突。

我不是第一个 发表于 2023-9-12 20:43:14

Mike_python小 发表于 2023-9-10 08:22
在多线程同时运行时,要想在遇到特定函数时只执行一次,可以使用同步机制来实现。以下是一种可能的解决方案 ...

还有一个问题,如果下次又遇到验证码呢?比如10分钟左右又遇到了验证码。

Mike_python小 发表于 2023-9-12 20:53:27

如果在一段时间后又遇到验证码,可以将上述的全局变量 `function_executed` 重新设置为 `False`,以便下次特定函数执行时可以再次执行。


import threading
import time

# 全局变量,用于标记特定函数是否已经执行
function_executed = False

# 特定函数
def special_function():
    global function_executed
    if not function_executed:
      # 执行特定操作,例如验证码的处理
      print("执行特定函数")
      function_executed = True

# 多线程任务
def worker():
    # 其他任务...

    # 在遇到特定函数时,只执行一次
    special_function()

    # 其他任务...

# 定时重置全局变量
def reset_variable():
    global function_executed
    while True:
      time.sleep(10 * 60)# 每隔10分钟重置一次
      function_executed = False

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

# 创建并启动重置全局变量的线程
reset_thread = threading.Thread(target=reset_variable)
reset_thread.start()

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

# 等待重置线程结束
reset_thread.join()


在上述示例中,新增了一个名为 `reset_variable` 的函数,该函数会周期性地重置全局变量 `function_executed`,这里使用了一个循环和 `time.sleep` 来实现定时重置。可以根据实际需求调整重置的时间间隔。

这样,在每次重置后,特定函数又可以被执行一次,以处理后续遇到的验证码或其他需要执行一次的操作。

请注意,对全局变量的访问和修改要进行线程同步,以避免多个线程同时修改导致的竞争条件。可以使用锁或其他同步机制来确保线程安全。

我不是第一个 发表于 2023-9-12 21:04:01

本帖最后由 我不是第一个 于 2023-9-12 21:06 编辑

      global function_executed
      i = request.i
      if i >= 5:
            if not self.function_executed:
                self.function_executed = True
                time.sleep(30)
                print(f'{i}这个是测试用的')
                self.function_executed = False

            print(f'{i}这就很六了')
      else:
            print(f'{i}小于五了')


我是这样设置的,if not self.function_executed 后面的代码过于复杂,会导致其他线程也进来,所有就立马设置了self.function_executed = True, 等运行完后再设置self.function_executed = False,验证后效果没毛病,不知道有隐患没有。

我不是第一个 发表于 2023-9-12 22:15:13

Mike_python小 发表于 2023-9-12 20:53
如果在一段时间后又遇到验证码,可以将上述的全局变量 `function_executed` 重新设置为 `False`,以便下次 ...

好像搞错了{:5_109:}
第一个线程进去reset_variable执行后,其他线程不执行reset_variable,但同时必须要处于等待状态,因为要过验证码,其他线程必须获取reset_variable的结果才能继续执行。
页: [1]
查看完整版本: 多线程问题