2

在我的程序中,我使用单个线程池来调度我的所有任务,例如定时器任务、非阻塞套接字 I/O 等。任务实际上是一个回调函数,它会在收到特定事件时执行。

架构是:

  1. 主线程调用 epoll() 来收集 I/O 事件,然后将 I/O 回调分派到线程池。

  2. 主线程也处理定时器超时,并将超时回调分派到线程池

  3. 在 I/O 回调中,可能会取消一个定时器任务,具体取决于 I/O 处理结果。

  4. 在一个 I/O 回调运行期间,不会监视对应的套接字是否有进一步的相同事件。

  5. 在一个定时器回调运行期间,该定时器任务将暂时从定时器任务队列中移除。

这是问题所在:

  1. 在池中的线​​程 A 正在运行计时器回调 T 期间。

  2. 池中的线程 B 可能正在运行另一个回调(为套接字 I/O 读取事件注册),在收到处理请求后,线程 B 决定删除定时器任务 T,但该定时器任务 T 正在由线程 A 执行.

我可以为定时器任务添加一个锁,但是我应该把锁放在哪里呢?我不能将锁对象放在定时器任务结构中,因为当我决定释放任务对象时,我必须已经获得了锁,释放并持有锁,可能会导致未定义的行为:

pthread_mutex_lock(T->mutex);
 free(T);
 /*without a pthread_mutex_unlock(T->mutex);*/

如果另一个线程被阻塞会发生什么:

pthread_mutex_lock(T->mutex);

如果没有解决这些问题,我将无法继续我的工作。请帮助我!

我应该在单个进程中为不同类型的任务使用单独的线程池吗?还是只使用单线程?

任何建议表示赞赏!

4

2 回答 2

0

你不能参考计算任务吗?当池中的线程 A 正在运行计时器回调 T 时,您标记它(例如使用互锁增量)。完成后,您减少使用量。在使用量为零之前无法释放它。

于 2012-09-17T10:04:17.043 回答
0

您可以使用受其自己的互斥锁保护的全局计时器表。该表实际上不需要是全局的,但可以属于某个集合,例如拥有您正在执行 I/O 的所有事物的任何集合。

然后使用这个逻辑:

创建一个计时器

  1. 锁定全局表。

  2. 将计时器添加到处于“待定”状态的全局表中。

  3. 解锁全局表。

  4. 用线程池调度定时器。

要触发计时器

  1. 锁定全局表。

  2. 检查计时器的状态。如果它不是“待定”,则删除计时器,解锁表并停止。

  3. 将计时器的状态更改为“正在触发”。

  4. 解锁全局表。

  5. 执行定时器操作。

  6. 锁定全局表。

  7. 从桌子上取下计时器。

  8. 解锁全局表。

要取消计时器

  1. 锁定全局表。

  2. 找到计时器。如果它的状态是“待定”,则将其更改为“已取消”。不要删除它。

  3. 解锁全局表。

于 2012-09-17T09:48:05.603 回答