互斥锁和多线程问题

4
我有一个API(用C语言编写),允许任意数量的传入连接。每个连接都由独立的pthread处理,当客户端连接到API时创建。 这些连接中的每一个都可以(但不必)更改服务器的属性,使得请求不能同时处理。
我的代码基本上遵循以下结构:
pthread_mutex_t lock;
void request_handler(char * request)
{
    pthread_mutex_lock(&lock);
    process_request(request);
    pthread_mutex_unlock(&lock);
}

假设现在正在处理一个长时间的请求(例如10秒)。在此期间,另外5个请求进来了,因此另外5个线程会到达pthread_mutex_lock函数。
  • 它们只是等待并按照预期继续执行(一个接一个地服务)吗?
我之所以问这个问题,是因为这是我所期望的,但在官方文档中没有找到多个并发线程的示例。
  • 是否保证按照接收顺序处理请求,还是在长请求完成后,任何一个等待的线程都可以开始执行?
我的代码不需要严格按顺序执行,但我想事先知道可以预期什么,以便正确设计我的代码。
我也读过关于递归mutex的内容,但由于一些原因,我想避免使用它们。此外,根据构造,我的代码不会尝试从一个单独的pthread多次锁定。

不,没有任何顺序得到保证。在锁被释放后,第一个获取锁的人将获得它。没有排队机制。如果您想控制顺序,您需要使用信号量。 - cs95
@Coldspeed所说的是对的,但实际上,操作系统很可能会将等待的线程排队到互斥锁并按照它们“到达”的顺序释放它们,但不要把它当成铁板钉钉的规则 :) - ThingyWotsit
首先,创建/销毁线程是非常耗时的。最好使用一个“线程池”(详细信息请谷歌搜索),这样所有的创建时间都集中在程序的开头,而销毁时间则集中在程序的结尾,并且只会发生一次,而不是在每个连接/断开连接上都发生。 - user3629249
发布的代码将序列化处理连接。最好不要序列化,而是将请求交给可用的线程进行处理。 - user3629249
@user3629249 感谢您的建议,但我的应用程序是为低性能硬件设计的,而不是HPC,我宁愿不要有大量线程闲置并消耗资源(我事先不知道最多需要多少线程)。因此,我愿意投入创建线程的成本,因为它提高了源代码的可读性。请求被序列化,因为某些请求可能会导致数据结构的调整大小,如果同时发生多次,这可能很容易导致严重问题。 - MrD
1个回答

2

互斥锁确保每次只有一个线程进入临界区,在你的代码中,就是调用 process_request() 函数。一旦线程 t 获取到锁,任何后续线程都必须等待直到 t 释放它。

如果有多个这样的线程同时到达,谁先获得机会取决于操作系统对线程的调度,这并不确定,每次运行程序可能都不同。但是,保证每次只有一个线程可以通过。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接