原子操作实现无锁同步

原子操作是我们常常听到的一个概念,合理使用原子操作可以显著降低因为锁同步耗费时间。文章首先将会讨论以下问题:

  • 为什么需要互斥锁
  • 互斥锁的成本
  • 如何用原子操作替代互斥锁

一、为什么需要互斥锁?

主要为了解决多个线程并发造成的数据争抢导致的脏数据。下面的程序创建了十个线程,线程执行的内容都是将全局变量count自加1一万次,按照正常逻辑,最终的count结果应该是:10W。

#include <iostream>
#include <vector>
#include <algorithm>
#include <thread>
#include <atomic>
#include <chrono>
#include <mutex>

using namespace std::chrono_literals;

int count;
std::mutex lo;

void addOne()
{
    for(int i=0;i<10000;i++)
    {
        count++;
    }
}

int main()
{
    auto s=std::chrono::steady_clock::now();
    std::vector<std::thread * > pths; 
    std::generate_n(std::back_inserter(pths),10,[]{return new std::thread(addOne);});
    std::for_each(pths.begin(),pths.end(),[](std::thread *ele){ele->join();});
    auto e=std::chrono::steady_clock::now();
    std::chrono::duration<double,std::milli> d=e-s;

    std::cout<<count<<std::endl;
    std::cout<<d.count()<<"ms"<<std::endl;

    return 0;
}

输出结果如下:

42414
0.489784ms

结果表明,数据没有被正确的加到10W。这是为什么?一个线程正在进行自增操作时,另一个线程打断了这个操作,导致最开始的线程再也没有办法完成这个操作了,我们说这两个线程进行了数据争抢,争抢的结果是打断无法正确增加,打断多少次就会少多少次自增操作。对修改数据代码部分进行加锁可以避免这种情况。

二、互斥锁的成本

修改方式也比较简单,只需要在count前后加上lock和unlock。

std::mutex lo;

void addOne()
{
    for(int i=0;i<10000;i++)
    {
        lo.lock();
        count++;
        lo.unlock();
    }
}

结果如下:

100000
12.6528ms

现在count被正确增加到了10W,但是时间却从之前(未加锁前)的0.46ms增加到了12.54ms,增加了26.26倍,问题解决了,但是时间却成倍增加。这时候就要到我们的主角出场了———原子操作。

三、原子操作实现lock-free

原子操作头文件:

#include <atomic>

然后将count声明为atomic_int:

atomic_int count(0);

代码如下:

std::atomic_int count(0);
std::mutex lo;

void addOne()
{
    for(int i=0;i<10000;i++)
    {
        count++;
    }
}
100000
1.93808ms

数据被正确的增加到10W,时间比什么都不做的只增加了54%的时间。


【1】https://zhuanlan.zhihu.com/p/340359732

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值