鱼C论坛

 找回密码
 立即注册
查看: 2453|回复: 6

[已解决]多线程问题

[复制链接]
发表于 2023-9-9 22:32:00 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
多线程同时运行时,在遇到特定函数时,怎么只执行一次。
比如遇到验证码时。
最佳答案
2023-9-12 20:53:27
如果在一段时间后又遇到验证码,可以将上述的全局变量 `function_executed` 重新设置为 `False`,以便下次特定函数执行时可以再次执行。


  1. import threading
  2. import time

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

  5. # 特定函数
  6. def special_function():
  7.     global function_executed
  8.     if not function_executed:
  9.         # 执行特定操作,例如验证码的处理
  10.         print("执行特定函数")
  11.         function_executed = True

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

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

  17.     # 其他任务...

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

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

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

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

  36. # 等待重置线程结束
  37. reset_thread.join()
复制代码


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

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

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

本帖被以下淘专辑推荐:

小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2023-9-9 22:32:10 | 显示全部楼层
可以使用信号量(Semaphore)来解决这个问题。

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

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

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

  1. import threading

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

  4. def do_something():
  5.     # 尝试获取信号量
  6.     semaphore.acquire()
  7.    
  8.     # 执行特定函数
  9.     # ...

  10.     # 释放信号量
  11.     semaphore.release()

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

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

  20. # 等待所有线程完成
  21. for t in threads:
  22.     t.join()
复制代码


在上面的代码中,当多个线程同时运行时,只有一个线程可以获取信号量并执行特定函数,其他线程将被阻塞。当执行特定函数的线程释放信号量后,其他线程可以获取信号量并执行特定函数。这样就可以保证特定函数只被执行一次。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

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

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

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

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

  1. import threading

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

  4. # 特定函数
  5. def special_function():
  6.     global function_executed
  7.     if not function_executed:
  8.         # 执行特定操作,例如验证码的处理
  9.         print("执行特定函数")
  10.         function_executed = True

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

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

  16.     # 其他任务...

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

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

复制代码

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

请注意,全局变量的访问要确保线程安全,可以使用锁机制或其他同步原语来保证多个线程对全局变量的访问操作不会冲突。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

还有一个问题,如果下次又遇到验证码呢?比如10分钟左右又遇到了验证码。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-9-12 20:53:27 | 显示全部楼层    本楼为最佳答案   
如果在一段时间后又遇到验证码,可以将上述的全局变量 `function_executed` 重新设置为 `False`,以便下次特定函数执行时可以再次执行。


  1. import threading
  2. import time

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

  5. # 特定函数
  6. def special_function():
  7.     global function_executed
  8.     if not function_executed:
  9.         # 执行特定操作,例如验证码的处理
  10.         print("执行特定函数")
  11.         function_executed = True

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

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

  17.     # 其他任务...

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

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

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

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

  36. # 等待重置线程结束
  37. reset_thread.join()
复制代码


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

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

请注意,对全局变量的访问和修改要进行线程同步,以避免多个线程同时修改导致的竞争条件。可以使用锁或其他同步机制来确保线程安全。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-9-12 21:04:01 | 显示全部楼层
本帖最后由 我不是第一个 于 2023-9-12 21:06 编辑
  1.         global function_executed
  2.         i = request.i
  3.         if i >= 5:
  4.             if not self.function_executed:
  5.                 self.function_executed = True
  6.                 time.sleep(30)
  7.                 print(f'{i}这个是测试用的')
  8.                 self.function_executed = False

  9.             print(f'{i}这就很六了')
  10.         else:
  11.             print(f'{i}小于五了')
复制代码



我是这样设置的,if not self.function_executed 后面的代码过于复杂,会导致其他线程也进来,所有就立马设置了self.function_executed = True, 等运行完后再设置self.function_executed = False,验证后效果没毛病,不知道有隐患没有。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

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

好像搞错了
第一个线程进去reset_variable执行后,其他线程不执行reset_variable,但同时必须要处于等待状态,因为要过验证码,其他线程必须获取reset_variable的结果才能继续执行。
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-22 17:19

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表