gpt4 book ai didi

c - 抢占、pthread_spin_lock 和原子内置

转载 作者:太空狗 更新时间:2023-10-29 11:32:44 26 4
gpt4 key购买 nike

根据这个问题here使用 pthread_spin_lock 锁定关键部分是危险的,因为线程可能会被调度程序中断,而其他线程可能会在该资源上保持旋转状态。

假设我决定从 pthread_spin_lock 切换到通过 atomic built-in + compare_and_swap idion 实现的锁:这件事会改善还是我仍然会遇到这个问题?

自从使用 pthread 后,禁用抢占似乎没什么用,如果我使用通过原子实现的锁或任何我可以查看的东西,我能做些什么吗?

我对锁定一个小的关键区域很感兴趣。

最佳答案

pthread_mutex_lock 通常有一个快速路径,它使用原子操作来尝试获取锁。如果没有锁,这会非常快。只有当锁已经持有时,线程才会通过系统调用进入内核。内核获取一个自旋锁,然后重新尝试获取互斥锁,以防它在第一次尝试后被释放。如果此尝试失败,则将调用线程添加到与互斥锁关联的等待队列,并执行上下文切换。内核还在互斥量中设置一个位来指示有一个等待线程。

pthread_mutex_unlock 也有一个快速路径。如果等待线程标志被清除,它可以简单地释放锁。如果设置了标志,则线程必须通过系统调用进入内核,以便唤醒等待的线程。同样,内核必须获得一个自旋锁,以便它可以操纵其线程控制数据结构。如果最终没有线程等待,内核可以释放锁。如果有线程在等待,它会变为可运行状态,互斥体的所有权会在不释放的情况下转移。

这个小舞蹈中有许多微妙的竞争条件,希望一切正常。

由于尝试获取锁定互斥锁的线程被上下文切换,它不会阻止拥有互斥锁的线程运行,这使所有者有机会退出其关键部分并释放互斥锁。

相比之下,尝试获取锁定的自旋锁的线程只会自旋,从而消耗 CPU 周期。这有可能阻止拥有自旋锁的线程退出其临界区并释放锁。旋转线程可以在其时间片被消耗时被抢占,从而允许拥有锁的线程最终重新获得控制权。当然,这对性能来说不是很好。

在实践中,自旋锁用于当线程拥有锁时不可能被抢占的地方。内核可以设置一个 per-cpu 标志以防止它从中断服务例程执行上下文切换(或者它可以提高中断优先级以防止可能导致上下文切换的中断,或者它可以完全禁用中断)。用户线程可以通过提高其优先级来防止自己被(同一进程中的其他线程)抢占。请注意,在单处理器系统中,防止当前线程被抢占就不需要自旋锁。或者,在多处理器系统中,您可以将线程绑定(bind)到 cpus(cpu 亲和性),这样它们就不能相互抢占。

所有的锁最终都需要一个原子原语(好吧,高效的锁;参见 here 的反例)。如果互斥量竞争激烈,互斥量可能效率低下,导致线程不断进入内核并进行上下文切换;特别是如果临界区小于内核开销。自旋锁可以更有效,但前提是所有者不能被抢占并且关键部分很短。请注意,当线程尝试获取锁定的互斥量时,内核仍必须获取自旋锁。

就个人而言,我会使用原子操作来处理共享计数器更新之类的事情,而使用互斥锁来处理更复杂的操作。只有在分析之后,我才会考虑用自旋锁替换互斥锁(并弄清楚如何处理抢占)。请注意,如果您打算使用条件变量,则别无选择,只能使用互斥量。

关于c - 抢占、pthread_spin_lock 和原子内置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22385788/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com