c - 服务器架构之谜,C编程

标签 c multithreading architecture locking pthreads

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

架构是:

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

  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);

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

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

欢迎任何建议!

最佳答案

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

然后使用这个逻辑:

创建计时器:

  1. 锁定全局表。

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

  3. 解锁全局表。

  4. 使用线程池安排定时器。

触发计时器:

  1. 锁定全局表。

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

  3. 将计时器的状态更改为“firing”。

  4. 解锁全局表。

  5. 执行定时器操作。

  6. 锁定全局表。

  7. 从表中删除计时器。

  8. 解锁全局表。

取消计时器:

  1. 锁定全局表。

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

  3. 解锁全局表。

关于c - 服务器架构之谜,C编程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12456267/

相关文章:

php - 数据处理的设计模式? (MVC 替代方案)

c - 在 C 中直接操作字符串中的 long 值

architecture - 从 CQRS 写入端数据库读取数据

C++ - 使用相同的函数从文件或内存缓冲区中读取

c# - 在 C# 中将数据传递到回调方法(通过 BeginInvoke)

c - Peterson的线程链表算法(C语言)

c++ - 节点预分配 vector 中的无锁树节点分配

.net - 优化每分钟大量数据库请求的应用程序

C 程序读取两个模式之间的文件行并将其打印出来

c++ - 使用波浪号获取 int 的 MAX 值