我最近在文件memcached.h
中阅读了memcached的源代码。我找到了这段代码:
static inline int mutex_lock(pthread_mutex_t *mutex)
{
while (pthread_mutex_trylock(mutex));
return 0;
}
我只是想知道为什么不直接使用pthread_mutex_lock
。上述代码有什么优势?
sleep 1 or 2 seconds
看起来更合理之后 pthread_mutex_trylock
,因为它不会浪费CPU资源。
有什么想法吗?
感谢。
答案 0 :(得分:1)
这本质上是一个自旋锁。我们的想法是让线程避免在内核中阻塞,这可能会损害线程的效率。
这种自旋锁只有在锁具有相当低的争用率和/或被保持很短的时间内才有意义。显然,如果你在while
循环中进行一系列迭代,那也会导致效率下降。
另外,我相信libc通常会在阻塞之前通过一点点旋转来实现pthread_mutex_lock()
,但是我必须深入研究(可能很难阅读)来源来验证它。
另一点 - 在单核系统上运行这将是非常愚蠢的代码,但这些代码正在灭绝。
答案 1 :(得分:0)
这样你就可以让另一个函数等待资源被解锁。这也是pthread_mutex_lock的作用。但是,try_lock可用于防止死锁条件,如优先级反转情况。由于该函数返回错误而不是阻塞进程(如pthread_mutex_lock那样)。
但我同意这基本上实现了pthread_mutex_lock,不同之处在于您可以扩展此自定义函数以防止死锁。
编辑: 如果您添加几秒钟的睡眠,可能会再次声明资源,因为几秒钟是相对较长的时间。通过不添加睡眠,您可以在可能的情况下强制锁定资源,因此与等待相比更加公平。
假设我们有3个线程B,C,D
正在等待A
锁定的同一资源
假设我们分别有1秒的睡眠和B,C,D
的到达时间。
0.1, 0.15, 0.2
所有三个线程都需要0.25秒的资源(为简单起见),A
需要0.1秒。
然后,如果每个线程每秒都需要资源,那么我们可能会遇到这种情况
A
1.0
{}发布资源,然后资源B
可以在1.1
声明它并在0.35
发布,其他任何线程都无法声明它,因为它们正等着这个时刻。然后,资源A
在时间1.9
获得收益并再次声明资源并在2.0
处释放它。之后B
时,线程2.1
再次声明它。这可确保只有资源A
和B
才能声明资源。因此,我们会遇到线程C
和D
的饥饿。
当然这是糟糕的设计,但是你应该在编写函数时使用它来锁定资源。但是,使用随机睡眠将解决此问题,但您需要再次了解有关资源使用的知识。