根据这个问题, 在这里通过使用pthread_spin_lock是危险的locking关键部分,因为线程可能会被调度程序中断,并且该资源上的其他线程内容可能会被旋转。
假设我决定从pthread_spin_lock切换到通过primefaces内置+ compare_and_swap idion实现的locking:这个事情会改善还是会受到这个问题的困扰?
因为用pthread它似乎没有什么禁用抢占,有什么我可以做的情况下,我使用通过primefaces实现的锁或任何我可以看看?
在linux中,如果我尽可能快地调用send(),为什么我会丢失UDP数据包?
后备列表vs低碎片堆
目前的C ++最佳实践和IDE
在Linux上的C + +装载NTFS设备?
在multithreading过程中处理信号的例子
有没有办法从UTF8转换为ISO-8859-1?
如何使用emacs在Linux中debuggingc / c ++源代码?
Windows CreateFileMapping:具有相同备份文件的不同文件映射对象
pthread_mutex_lock通常有一个快速路径,它使用原子操作来获取锁。 如果锁没有,这可以是非常快的。 只有当锁已经被锁定,线程才会通过系统调用进入内核。 内核获取自旋锁,然后重新尝试获取互斥锁,以防自第一次尝试释放互斥锁。 如果此尝试失败,则将调用线程添加到与该互斥锁关联的等待队列中,并执行上下文切换。 内核还在互斥体中设置了一个位,表示有一个等待线程。
pthread_mutex_unlock也有一个快速路径。 如果等待的线程标志清除,则可以简单地释放该锁。 如果标志被设置,线程必须通过系统调用进入内核,以便等待的线程可以被唤醒。 同样,内核必须获得一个自旋锁,以便它可以操作它的线程控制数据结构。 如果没有线程在等待,锁可以被内核释放。 如果有一个线程正在等待,它就会运行,并且互斥量的所有权被转移而不被释放。
这个小舞蹈有许多微妙的竞赛条件,希望一切正常。
由于尝试获取锁定的互斥锁的线程被切换到上下文环境,因此它不会阻止拥有互斥锁的线程运行,从而使所有者有机会退出其临界区并释放互斥锁。
相反,尝试获取锁定旋转锁的线程只是旋转,消耗cpu周期。 这有可能阻止拥有自旋锁的线程退出其关键部分并释放锁。 旋转的线程在其时间片被消耗时可被抢占,从而允许拥有锁的线程最终重新获得控制权。 当然,这对于性能来说并不好。
在实践中,使用自旋锁的地方是,在拥有锁的情况下线不可能被抢占。 内核可能会设置一个per-cpu标志,以防止它从中断服务程序执行上下文切换(或者可能会提高中断优先级以防止可能导致上下文切换的中断,或者可能完全禁用中断)。 用户线程可以通过提高优先级来防止自己被抢占(由同一进程中的其他线程抢占)。 请注意,在单处理器系统中,防止当前线程被抢占,从而不需要自旋锁定。 或者,在多处理器系统中,可以将线程绑定到cpu(cpu affinity),以便它们不能抢占彼此。
所有的锁最终都需要一个原子基元(很好,高效的锁;参见这里的一个反例)。 如果互斥性很强,互斥锁可能效率低下,导致线程不断进入内核并进行上下文切换; 特别是如果临界区小于内核开销。 旋转锁可以更有效率,但只有当拥有者不能被抢占和关键部分短。 请注意,当线程尝试获取锁定的互斥锁时,内核仍然必须获取旋转锁定。
就个人而言,我会使用原子操作的东西,如共享计数器更新,互斥和更复杂的操作。 只有在分析之后,我才会考虑用自旋锁代替互斥锁(并找出如何处理抢占)。 请注意,如果您打算使用condvars,则别无选择,只能使用互斥锁。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。