在我的程序中,我使用单个线程池来调度我的所有任务,如定时器任务、非阻塞套接字 I/O 等。任务实际上是一个回调函数,当接收到特定事件时将执行该回调函数。
架构是:
主线程调用 epoll() 来收集 I/O 事件,然后将 I/O 回调分派(dispatch)给线程池。
主线程还处理定时器超时,并将超时回调调度到线程池
在I/O回调中,根据I/O处理结果,可能会取消一个定时器任务。
在一个 I/O 回调运行期间,不会监视相应的套接字是否有其他相同的事件。
在一个定时器回调运行期间,该定时器任务将暂时从定时器任务队列中移除。
问题是:
在池中的线程 A 运行定时器回调 T 期间。
池中的线程 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 的所有东西的任何东西。
然后使用这个逻辑:
创建计时器:
锁定全局表。
将计时器添加到处于“待定”状态的全局表。
解锁全局表。
使用线程池安排定时器。
触发计时器:
锁定全局表。
检查计时器的状态。如果不是“待定”,则删除计时器,解锁表格,然后停止。
将计时器的状态更改为“firing”。
解锁全局表。
执行定时器操作。
锁定全局表。
从表中删除计时器。
解锁全局表。
取消计时器:
锁定全局表。
找到计时器。如果它的状态是“待定”,则将其更改为“已取消”。不要删除它。
解锁全局表。
关于c - 服务器架构之谜,C编程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12456267/