从同步互斥机制到智能指针使用成本

来源:互联网 发布:淘宝介入买家如何举证 编辑:程序博客网 时间:2024/05/16 09:32

作者:CppExplore  http://www.cppblog.com/CppExplore/http://blog.csdn.net/cppexplore同步发布

一 semaphore机制
古老的信号量机制,80年代初,从System V体系中产生,称为System v信号量。90年代,Posix标准确立,其中的信号量称为posix信号量。当前linux系统支持这两种信号量(man semget/ man sem_post)。System v信号量为有名信号量,可以用于多进程间的互斥同步。posix信号量分有名和无名两种,当前linux只支持无名信号量,可以用于多线程之间的互斥同步,通过共享内存也可以用于多进程之间。
信号量属于内核级别的互斥同步机制,相关调用总是陷入内核态,属于功能强大/重量级的实现。

二 spinlock机制
多核SMP的cpu流行后,出现的新的互斥同步机制。spinlock实现原理为用户态循环尝试机制,不陷入内核态进行线程切换。spinlock的原子性通过CAS(CompareAndSwap)原语实现。使用spinlock时,应该保证保护区间内代码执行迅速,不应该存在io等耗时操作。

多核系统下,针对可快速执行的保护区使用用户态循环尝试机制,可以保证执行线程不需要引起上下文切换即可快速执行通过,这种机制也被形象的称为lock-free机制。我们可以这样理解:lock-free机制即为循环尝试,spinlock是它的具体实现。

 

spinlock的实现有多种,常见的有pthread_spin_lock,该spinlock无限制循环尝试,在多核环境下并且保护区代码执行迅速时,执行线程很快可以拿到锁,但当单核环境或者保护区代码执行慢速时,则会耗尽该线程拥有的时间片之后交出cpu,造成cpu的浪费。另一常见的spinlock是boost智能指针中的实现,进行3次无间断的循环CAS原语判断,之后若再次失败,则调用sleep族函数,交出cpu执行权,待再次分配到cpu时间片后继续进行CAS原语判断操作。


三 mutex机制
mutex属于os之上的再次封装实现。在linux2.6内核上,线程库为nptl,其中的mutex基于futex机制实现,它的实现原理,简单说就是spinlock+semaphore,首先使用spinlock尝试,可以拿到锁则直接向下执行,拿不到锁则执行semaphore机制,陷入内核态,进入线程切换。
在多核环境下,当mutex保护的代码段内无io操作,执行很快时,大多数情况下通过spinlock都可拿到锁,不需要陷入内核态。


四 为智能指针正名(boost)
智能指针的引用计数仅仅为一个整型变量的增减,属于执行迅速的典型,使用spinlock机制保护,最新boost版本中仅仅是spinlock,而非mutex。从性能角度说,使用智能指针的现象是cpu略微上升(循环尝试导致),而并发量/单个请求的响应时间并无明显影响。proactor机制实现的网络层,智能指针基本无法绕过,刻意避免带来的只能是丑陋的代码和维护量的上升。但线程之间尽量避免传递指针(智能指针),通过传递id等代替。
智能指针有它使用的场景,不能滥用,也不能刻意避免。

原创粉丝点击