我是linux和linux线程的新手.我花了一些时间谷歌搜索试图理解可用于线程同步的所有函数之间的差异.我还有一些问题.
我找到了所有这些不同类型的同步,每个同步都有许多锁定,解锁,测试锁等功能.
> gcc原子操作
> futexes
>互斥体
>自旋锁
> seqlocks
> rculocks
>条件
>信号量
我当前(但可能有缺陷)的理解是这样的:
信号量是进程范围的,涉及文件系统(实际上我假设),并且可能是最慢的.
Futexes可能是互斥锁,自旋锁,seqlocks和rculocks使用的基本锁定机制. Futexes可能比基于它们的锁定机制更快.
自旋锁不会阻塞,从而避免上下文波动.然而,它们避免了上下文切换,代价是消耗cpu上的所有循环,直到释放锁定(旋转).出于显而易见的原因,它们应仅应用于多处理器系统.永远不要睡在螺旋锁中.
如果作者更改了工作所基于的数据,seq锁只会告诉您何时完成工作.在这种情况下,您必须返回并重复工作.
原子操作是最快的同步调用,并且可能在所有上述锁定机制中使用.您不希望对共享数据中的所有字段使用原子操作.当您访问多个数据字段时,您希望在锁定标志上使用锁(互斥锁,futex,旋转,seq,rcu)或单个原子操作.
我的问题是这样的:
>到目前为止我对我的假设是否正确?
>有谁知道各种选项的cpu周期成本?我正在为应用添加并行性,因此我们可以获得更好的响应时间,但每个盒子运行的应用实例更少.表演是最重要的考虑因素.我不想使用上下文切换,旋转或许多额外的cpu周期来读取和写入共享内存.我绝对关心消耗的cpu周期数.
>哪个(如果有的话)锁可以防止调度程序中断线程或中断…或者我只是一个白痴,所有同步机制都会这样做.什么样的中断被阻止?我可以阻止锁定线程的cpu上的所有线程或线程吗?这个问题源于我担心中断一个线程,该线程持有一个非常常用的函数.我希望调度程序可能会调度任何可能会遇到此函数的其他工作者,然后因为它被锁定而阻塞.在带有锁的线程被重新安排并完成之前,将浪费大量上下文切换.我可以重新编写这个函数以最小化锁定时间,但它通常被称为我想使用锁来防止中断…跨所有处理器.
>我正在编写用户代码…所以我得到软件中断,而不是硬件中断……对吗?我应该远离任何带有“irq”字样的功能(旋转/ seq锁).
>哪些锁用于编写内核或驱动程序代码,哪些用于用户模式?
>有没有人认为使用原子操作让多个线程通过链表移动是疯了?我想通过原子方式将当前项指针更改为列表中的下一个项.如果尝试有效,则线程可以安全地使用当前项在移动之前指向的数据.现在,其他线程将沿列表移动.
> futexes?有没有理由使用它们而不是互斥体?
>当没有工作时,有没有比使用条件睡眠线程更好的方法?
>当使用gcc原子操作,特别是test_and_set时,我可以通过首先进行非原子测试然后使用test_and_set来确认来提高性能吗?我知道这将是特定于案例的,所以情况就是如此.有数以千计的工作项目.每个工作项都有一个初始化为0的标志.当一个线程具有对工作项的独占访问权时,该标志将为1.会有很多工作线程.一旦线程正在寻找工作,他们就可以非原子地测试1.如果他们读取1,我们肯定知道工作不可用.如果他们读零,他们需要执行原子test_and_set来确认.因此,如果原子test_and_set是500个cpu周期,因为它禁用流水线操作,导致cpu通信和L2缓存刷新/填充….并且一个简单的测试是1个周期….然后只要我有一个更好的比率当它磕磕绊绊已经完成的工作项目时,500比1 ……这将是一场胜利.
我希望使用互斥锁或自旋锁来保护代码段,我希望一次只能访问SYSTEM(而不是cpu)上的一个线程.我希望谨慎地使用gcc原子操作来选择工作并尽量减少互斥锁和自旋锁的使用.例如:可以检查工作项中的标志以查看线程是否已经工作(0 =否,1 =是或正在进行中).一个简单的test_and_set告诉线程它是否有效或需要继续.我希望在工作时使用条件唤醒线程.
谢谢!