Linux C++ 无锁编程 cas

30 篇文章 0 订阅
29 篇文章 0 订阅

高并发服务器经常用到多线程编程,需要对共享数据进行操作,为了保护数据的正确性,有一种有效的方法就是加锁pthread_mutex_t。但是加锁会引起性能的下降,多个线程竞争同一个锁,抢占失败后强制上下文切换。还有一种方法就是使用原子指令。有一个重要的方法叫做CAS(compare and swap)。下面是CAS的伪代码


int compare_and_swap(int* reg, int oldval, int newval)
{
  ATOMIC();
  int old_reg_val = *reg;
  if (old_reg_val == oldval)
     *reg = newval;
  END_ATOMIC();
  return old_reg_val;
}


使用的时候一般都是定义三个全局变量(int reg=0,int old=0,int new=1;),所有线程都可以访问到。

int reg=0,int old=0,int new=1;

main()

{

do{

int ret = compare_and_swap(&reg,old,new);

}while(ret!=reg)

//只有ret!=reg的线程才可以通过

}



下面计算count的值,多个线程计算1加到400000。分别统计使用锁和原子操作使用的时间。


/*************************************************************************


    > File Name: threadsync.c
    > Author: chenhui
    > Mail: ********* 
    > Created Time: 2016年02月29日 21:53:40
 ************************************************************************/


#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/time.h>
#include "threadLock.h"


int64_t count=0;
int64_t count2=0;


int atomic_mutex = 0;
int lock = 0;
int unlock = 1;


pthread_mutex_t count_mutex=PTHREAD_MUTEX_INITIALIZER;
void *addNum(void*)//.c文件时没加void*,可以编译运行。.cpp文件时编译不过(pthread_create(,,addNum,))提示类型转换无效
{
int i=1;
for(;i<=400000;i++)
{
ThreadLock lock(&count_mutex);
count+=i;
}
}


void *addNum2(void*)
{
int i=1;
for(;i<=400000;i++)
{
CASFreeLock casLock(atomic_mutex,lock,unlock);
count2+=i;
}
}


int64_t getSystemTimeMs()
{
    struct timeval timeNow;
    gettimeofday(&timeNow, NULL);
    return timeNow.tv_sec*1000 + timeNow.tv_usec/1000;
}


int main()
{
int64_t timeStart,timeEnd;
timeStart = getSystemTimeMs();
pthread_t p1,p2,p3,p4;
pthread_create(&p1,NULL,addNum,NULL);
pthread_create(&p2,NULL,addNum,NULL);
pthread_create(&p3,NULL,addNum,NULL);
pthread_create(&p4,NULL,addNum,NULL);


pthread_join(p1,NULL);
pthread_join(p2,NULL);
pthread_join(p3,NULL);
pthread_join(p4,NULL);


timeEnd = getSystemTimeMs();
printf("thread lock->count:%lld, time use=%lldms\n",count, (timeEnd-timeStart));
timeStart = getSystemTimeMs();
pthread_create(&p1,NULL,addNum2,NULL);
pthread_create(&p2,NULL,addNum2,NULL);
pthread_create(&p3,NULL,addNum2,NULL);
pthread_create(&p4,NULL,addNum2,NULL);


pthread_join(p1,NULL);
pthread_join(p2,NULL);
pthread_join(p3,NULL);
pthread_join(p4,NULL);
timeEnd = getSystemTimeMs();
printf("cas lock free->count2:%lld, time use=%lldms\n",count2, (timeEnd-timeStart));


return 0;
}



threadLock.h文件

#ifndef THREAD_LOCK
#define THREAD_LOCK


#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <stdio.h>


class ThreadLock
{
private:
pthread_mutex_t* mutexPtr;
public:
explicit inline ThreadLock(pthread_mutex_t *pm):mutexPtr(pm)//explicit 抑制隐式转换,inline加入符号表提高函数调用效率
{
//printf("lock of threadid:%d\n",pthread_self());//放在这里,打印出来的信息不准
pthread_mutex_lock(mutexPtr);
//printf("lock of threadid:%d\n",pthread_self());
}
inline ~ThreadLock()
{
//printf("unlock of threadid:%d\n",pthread_self());
pthread_mutex_unlock(mutexPtr);
}
};


class CASFreeLock
{
private:
int* mutex;
int* lock;
int* unlock;
public:
explicit inline CASFreeLock(int& m, int& l, int& u)
{
mutex = &m;
lock = &l;
unlock = &u;
//printf("mutex:%d,lock:%d,unlock:%d\n",*mutex,*lock,*unlock);


while(!__sync_bool_compare_and_swap(mutex, *lock, 1))
{
usleep(100000);//sleep 10ms
}
}
inline ~CASFreeLock()
{
//printf("~mutex:%d,lock:%d,unlock:%d\n",*mutex,*lock,*unlock);
__sync_bool_compare_and_swap(mutex, *unlock, 0);
}
};


#endif


/*
 * pthread_join使一个线程等待另一个线程结束。 代码中如果没有pthread_join主线程会很快结束从而使整个进程结束,
 * 从而使创建的线程没有机会开始执行就结束。
 * */
/*run:
 * g++ threadsync.cpp -o threadcas
 * ./threadcas.exe or ./threadcas
 * */


运行结果如下,通过结果可以看出使用cas原子操作比线程加锁的速度提高了15倍左右:

Administrator@huihui ~/Linux/thread
$ ./threadcas.exe
thread lock->count:320000800000, time use=5102ms
cas lock free->count2:320000800000, time use=313ms


Administrator@huihui ~/Linux/thread
$ ./threadcas.exe
thread lock->count:320000800000, time use=5187ms
cas lock free->count2:320000800000, time use=339ms


Administrator@huihui ~/Linux/thread
$ ./threadcas.exe
thread lock->count:320000800000, time use=5120ms
cas lock free->count2:320000800000, time use=317ms




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值