我非常好奇于不同同步原理的性能,于是对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. Csharp: read excel file using Open XML SDK 2.5

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  2. Ahjesus Nodejs01 环境搭建及运行

    访问http://nodejs.org/,根据系统选择下载文件,我用的win7 64 安装一路下一步直到完成 运行cmd输入node -v查看是否安装成功 成功会显示版本号 到此环境搭建完毕 ==== ...

  3. 「C语言」int main还是void main?

    从大一入学刚接触C到现在已满7个月了,虽然刚开始就知道```int main```才是标准的写法,但一直没有深刻理解为什么不能用```void main```而必须使用```int main```. ...

  4. C# 循环语句 for循环(嵌套 while 穷举 迭代)

    for循环的嵌套类似于if else 事例: 打印矩阵,外循环对应行,内循环对应列 for (int k = 1; k <= 5; k++) { for (int i = 1; i <= ...

  5. C# 分支语句

    选择语句 if,else if是如果的意思,else是另外的意思,if后面跟()括号内为判断条件,如果符合条件则进入if语句执行命令.如果不符合则不进入if语句.else后不用加条件,但是必须与if配 ...

  6. php对mysql数据库简单连接操作

    前些阵子忙完了公司前端静态页面的事情了之后,简单学习了下php的基础知识,今天想了想回顾一下php连接数据库的方式,写一下随笔存一下看看 php连接数据库端口和新建数据库 <?php $serv ...

  7. CRM2013版本 IOS APP 说明(IPhone、IPad)

    CRM2013版本 IOS APP 说明(IPhone.IPad) IPhone版本 首页 CRM APP在登录时输入账号信息,可以进行首面.其首页显示内容可以在CRM后台设置. 系统默认显示:Pho ...

  8. SharePoint 使用代码为页面添加WebPart

    传统的SharePoint实施中,我们通常会创建SharePoint页面,然后添加webpartzone,而后在上面添加webpart:但是有些情况下,也要求我们使用代码,将webpart添加到相应w ...

  9. SharePoint部署工具SPSD

    SharePoint Solution Deployer,绝对属于必备的SharePoint工具之一了. 下载,解压这个工具,会有如下的目录(没有Assemblies和DeployGAC.bat)解压 ...

  10. File类的常用方法

    public static void GetFileInfo()    {                File file=new File("e:","two.txt ...