我非常好奇于不同同步原理的性能,于是对atomic, spinlock和mutex做了如下实验来比较:

1. 无同步的情况

 #include <future>
#include <iostream> volatile int value = ; int loop (bool inc, int limit) {
std::cout << "Started " << inc << " " << limit << std::endl;
for (int i = ; i < limit; ++i) {
if (inc) {
++value;
} else {
--value;
}
}
return ;
} int main () {
auto f = std::async (std::launch::async, std::bind(loop, true, ));//开启一个线程来执行loop函数,c++11的高级特性
loop (false, );
f.wait ();
std::cout << value << std::endl;
}

通过clang编译器:

 clang++ -std=c++ -stdlib=libc++ -O3 -o test test.cpp && time ./test

运行:

 SSttaarrtteedd    

 real    0m0.070s
user 0m0.089s
sys 0m0.002s

从运行结果很显然的我们可以看出增减不是原子性操作的,变量value最后所包含的值是不确定的(垃圾)。

2. 汇编LOCK

 #include <future>
#include <iostream> volatile int value = ; int loop (bool inc, int limit) {
std::cout << "Started " << inc << " " << limit << std::endl;
for (int i = ; i < limit; ++i) {
if (inc) {
asm("LOCK");
++value;
} else {
asm("LOCK");
--value;
}
}
return ;
} int main () {
auto f = std::async (std::launch::async, std::bind(loop, true, )); //开启一个线程来执行loop函数,c++11的高级特性
loop (false, );
f.wait ();
std::cout << value << std::endl;
}
 SSttaarrtteedd    

 real    0m0.481s
user 0m0.779s
sys 0m0.005s

  在最后变量value得到了正确的值,但是这些代码是不可移植的(平台不兼容的),只能在X86体系结构的硬件上运行,而且要想程序能正确运行编译的时候必须使用-O3编译选项。另外,由于编译器会在LOCK指令和增加或者减少指令之间注入其他指令,因此程序很容易出现“illegal instruction”异常从而导致程序被崩溃。

3. 原子操作atomic

 #include <future>
#include <iostream>
#include "boost/interprocess/detail/atomic.hpp" using namespace boost::interprocess::ipcdetail; volatile boost::uint32_t value = ; int loop (bool inc, int limit) {
std::cout << "Started " << inc << " " << limit << std::endl;
for (int i = ; i < limit; ++i) {
if (inc) {
atomic_inc32 (&value);
} else {
atomic_dec32 (&value);
}
}
return ;
} int main () {
auto f = std::async (std::launch::async, std::bind (loop, true, ));
loop (false, );
f.wait ();
std::cout << atomic_read32 (&value) << std::endl;
}

运行:

 SSttaarrtteedd    

 real    0m0.457s
user 0m0.734s
sys 0m0.004s

最后结果是正确的,从所用时间来看跟汇编LOCK的差不多。当然原子操作的底层也是使用了LOCK汇编来实现的,只不过是使用了可移植的方法而已。

4. 自旋锁spinlock

 #include <future>
#include <iostream>
#include "boost/smart_ptr/detail/spinlock.hpp" boost::detail::spinlock lock;
volatile int value = ; int loop (bool inc, int limit) {
std::cout << "Started " << inc << " " << limit << std::endl;
for (int i = ; i < limit; ++i) {
std::lock_guard<boost::detail::spinlock> guard(lock);
if (inc) {
++value;
} else {
--value;
}
}
return ;
} int main () {
auto f = std::async (std::launch::async, std::bind (loop, true, ));
loop (false, );
f.wait ();
std::cout << value << std::endl;
}

运行:

 SSttaarrtteedd    

 real    0m0.541s
user 0m0.675s
sys 0m0.089s

最后结果是正确的,从用时来看比上述的慢点,但是并没有慢太多

5. 互斥锁mutex

 #include <future>
#include <iostream> std::mutex mutex;
volatile int value = ; int loop (bool inc, int limit) {
std::cout << "Started " << inc << " " << limit << std::endl;
for (int i = ; i < limit; ++i) {
std::lock_guard<std::mutex> guard (mutex);
if (inc) {
++value;
} else {
--value;
}
}
return ;
} int main () {
auto f = std::async (std::launch::async, std::bind(loop, true, ));
loop (false, );
f.wait ();
std::cout << value << std::endl;
}

运行:

 SSttaarrtteedd    

 real    0m25.229s
user 0m7.011s
sys 0m22.667s

互斥锁要比前面几种的慢很多

 Benchmark
Method Time (sec.)
No synchronization 0.070
LOCK 0.481
Atomic 0.457
Spinlock 0.541
Mutex 22.667

当然,测试结果会依赖于不同的平台和编译器(我是在Mac Air和clang上做的测试)。

原文链接:http://demin.ws/blog/english/2012/05/05/atomic-spinlock-mutex/

atomic, spinlock and mutex性能比较的更多相关文章

  1. std::atomic和std::mutex区别

    ​ ​std::atomic介绍​ ​模板类std::atomic是C++11提供的原子操作类型,头文件 #include<atomic>.​在多线程调用下,利用std::atomic可实 ...

  2. 内核必看: spinlock、 mutex 以及 semaphore

    linux 内核的几种锁介绍 http://wenku.baidu.com/link?url=RdvuOpN3RPiC5aY0fKi2Xqw2MyTnpZwZbE07JriN7raJ_L6Ss8Ru1 ...

  3. Pthreads并行编程之spin lock与mutex性能对比分析(转)

    POSIX threads(简称Pthreads)是在多核平台上进行并行编程的一套常用的API.线程同步(Thread Synchronization)是并行编程中非常重要的通讯手段,其中最典型的应用 ...

  4. spinlock,mutex,semaphore,critical section的作用与差别

    某年深信服的笔试题,考的就是多线程的同步.简单的解释下方便记忆: 1.spinlock:自旋锁.是专为防止多处理器并发而引入的一种锁. 2.mutex:相互排斥量. 仅仅有拥有相互排斥对象的线程才有訪 ...

  5. Any race is a bug. When there is a race, the compiler is free to do whatever it wants.

    https://mp.weixin.qq.com/s/pVJiFdDDKVx707eKL19bjA 谈谈 Golang 中的 Data Race 原创 ms2008 poslua 2019-05-13 ...

  6. Samsung_tiny4412(驱动笔记07)----spinlock,semaphore,atomic,mutex,completion,interrupt

    /*********************************************************************************** * * spinlock,se ...

  7. 浅谈Unity的渲染优化(1): 性能分析和瓶颈判断(上篇)

    http://www.taidous.com/article-667-1.html 前言 首先,这个系列文章做个大致的介绍,题目"浅谈Unity",因为公司和国内大部分3D手游开发 ...

  8. go sync.Mutex 设计思想与演化过程 (一)

    go语言在云计算时代将会如日中天,还抱着.NET不放的人将会被淘汰.学习go语言和.NET完全不一样,它有非常简单的runtime 和 类库.最好的办法就是将整个源代码读一遍,这是我见过最简洁的系统类 ...

  9. 【linux】spinlock 的实现

    一.什么是spinlock spinlock又称自旋锁,是实现保护共享资源而提出一种锁机制.自旋锁与互斥锁比较类似,都是为了解决对某项资源的互斥使用 无论是互斥锁,还是自旋锁,在任何时刻,最多只能有一 ...

随机推荐

  1. 【Unity】13.1 场景视图中的GI可视化

    分类:Unity.C#.VS2015 创建日期:2016-05-19 一.简介 在场景视图中设计不同的场景内容时,可以根据需要勾选相关的渲染选项,以便让场景仅显示其中的一部分或者全部渲染效果. 在这些 ...

  2. fibonacci封闭公式及矩阵连乘

    Description The Fibonacci sequence is the sequence of numbers such that every element is equal to th ...

  3. String系列

    String 简介 String 是java中的字符串,它继承于CharSequence.String类所包含的API接口非常多.为了便于今后的使用,我对String的API进行了分类,并都给出的演示 ...

  4. poi excel export 乱码

    1. Question Description: ~前端是get方式提交的,参数含有中文“测试” ~导出的excel,文件名正常, 而标题乱码 2. Solution: ~断点发现, 参数接收就是乱码 ...

  5. DirectShow程序运行过程简析

    这段时间一直在学习陆其明老师的<DirectShow开发指南>一书,书中对DirectShow的很多细节讲解清晰,但是却容易让人缺少对全局的把握.在学习过程中,整理了关于DirectSho ...

  6. MAC下 JDK环境配置、版本切换以及ADB环境配置

    网上方法,自己总结:亲测可行! 一.JDK环境配置.版本切换: 通过命令’jdk6′, ‘jdk7′,’jdk8’轻松切换到对应的Java版本: 1.首先安装所有的JDk:* Mac自带了的JDK6, ...

  7. 使用Python给要素添加序号

    在ArcGIS的属性表中,由于编辑修改的原因,默认的FID或OID并不连续,经常需要给要素添加连读的序号,可使用Python代码完成. rec=-1 def autoIncrement(): glob ...

  8. DevExpress.XtraGrid.Views 设置指定行的背景颜色 .

    如需要将指定行的背景设置颜色,可参考以下示例 1.事件:CustomDrawCell 2.示例: private void gridView1_CustomDrawCell(object sender ...

  9. Atitit。  工作流引擎的发展趋势

    Atitit.  工作流引擎的发展趋势 1.1. 图灵完备1 1.2. 图形化与文本化1 1.3. Jit1 1.4. Dsl化2 1.5. Oo2 1.6. 托管与本地代码的互操作2 1.7. 大型 ...

  10. PHP读取Excel文件内容

    PHP读取Excel文件内容   项目需要读取Excel的内容,从百度搜索了下,主要有两个选择,第一个是PHPExcelReader,另外一个是PHPExcel.   PHPExcelReader比较 ...