__sync_fetch_and_add,pthread_mutex_lock

线程安全

#define _GNU_SOURCE

#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
#include <sched.h>
#include <linux/unistd.h>
#include <sys/syscall.h>
#include <errno.h>
#include <linux/types.h>
#include <time.h>

#define INC_TO 1000000 // one million...

__u64 rdtsc()
{
  __u32 lo,hi;

    __asm__ __volatile__
    (
     "rdtsc":"=a"(lo),"=d"(hi)
    );

    return (__u64)hi<<32|lo;
}

int global_int0 = 0;
int global_int1 = 0;
int global_int2 = 0;

pthread_mutex_t count_lock = PTHREAD_MUTEX_INITIALIZER;


pid_t gettid( void )
{
    return syscall( __NR_gettid );
}

void *thread_routine0( void *arg )
{
    int i;
    int proc_num = (int)(long)arg;
    __u64 begin, end;
    struct timeval tv_begin,tv_end;
    __u64 timeinterval;
    cpu_set_t set;

    CPU_ZERO( &set );
    CPU_SET( proc_num, &set );

    if (sched_setaffinity( gettid(), sizeof( cpu_set_t ), &set ))
    {
        perror( "sched_setaffinity" );
        return NULL;
    }

    begin = rdtsc();
    gettimeofday(&tv_begin,NULL);
    for (i = 0; i < INC_TO; i++)
    {
         __sync_fetch_and_add( &global_int0, 1 );
    }
    gettimeofday(&tv_end,NULL);
    end = rdtsc();
    timeinterval =(tv_end.tv_sec - tv_begin.tv_sec) * 1000000 + (tv_end.tv_usec - tv_begin.tv_usec);
    fprintf(stderr,"proc_num :%d,__sync_fetch_and_add cost %llu CPU cycle,cost %llu us\n", proc_num, end-begin, timeinterval);

    return NULL;
}

void *thread_routine1( void *arg )
{
    int i;
    int proc_num = (int)(long)arg;
    __u64 begin, end;
    struct timeval tv_begin,tv_end;
    __u64 timeinterval;
    cpu_set_t set;

    CPU_ZERO( &set );
    CPU_SET( proc_num, &set );

    if (sched_setaffinity( gettid(), sizeof( cpu_set_t ), &set ))
    {
        perror( "sched_setaffinity" );
        return NULL;
    }

    begin = rdtsc();
    gettimeofday(&tv_begin,NULL);
    for (i = 0; i < INC_TO; i++)
    {
         global_int1++;
    }
    gettimeofday(&tv_end,NULL);
    end = rdtsc();
    timeinterval =(tv_end.tv_sec - tv_begin.tv_sec) * 1000000 + (tv_end.tv_usec - tv_begin.tv_usec);
    fprintf(stderr,"proc_num :%d,__sync_fetch_and_add cost %llu CPU cycle,cost %llu us\n", proc_num, end-begin, timeinterval);

    return NULL;
}


void *thread_routine2( void *arg )
{
    int i;
    int proc_num = (int)(long)arg;
    __u64 begin, end;

    struct timeval tv_begin,tv_end;
    __u64 timeinterval;
    cpu_set_t set;

    CPU_ZERO( &set );
    CPU_SET( proc_num, &set );

    if (sched_setaffinity( gettid(), sizeof( cpu_set_t ), &set ))
    {
        perror( "sched_setaffinity" );
        return NULL;
    }

    begin = rdtsc();
    gettimeofday(&tv_begin,NULL);

    for(i = 0;i<INC_TO;i++)
    {
        pthread_mutex_lock(&count_lock);
        global_int2++;
        pthread_mutex_unlock(&count_lock);
    }

    gettimeofday(&tv_end,NULL);
    end = rdtsc();

    timeinterval =(tv_end.tv_sec - tv_begin.tv_sec) * 1000000 + (tv_end.tv_usec - tv_begin.tv_usec);
    fprintf(stderr,"proc_num :%d,pthread lock cost %llu CPU cycle,cost %llu us\n", proc_num, end-begin, timeinterval);

    return NULL;
}

int main()
{
    int procs = 0;
    int i;
    pthread_t *thrs;

    // Getting number of CPUs
    procs = (int)sysconf( _SC_NPROCESSORS_ONLN );
    if (procs < 0)
    {
        perror( "sysconf" );
        return -1;
    }

    thrs = malloc( sizeof( pthread_t ) * procs );
    if (thrs == NULL)
    {
        perror( "malloc" );
        return -1;
    }

    printf( "Starting %d threads...\n", procs );

    for (i = 0; i < procs; i++)
    {
        if (pthread_create( &thrs[i], NULL, thread_routine0,
            (void *)(long)i ))
        {
            perror( "pthread_create" );
            procs = i;
            break;
        }
    }

    for (i = 0; i < procs; i++)
        pthread_join( thrs[i], NULL );

    printf("===== use automic method =====\n");
    printf("After doing all the math, global_int value is: %d\n", global_int0);
    printf("Expected value is: %d\n", INC_TO * procs );
    printf("Correct rate: %f%\n\n", (double)(((double)global_int0)/((double)(INC_TO * procs)) * 100));

    for (i = 0; i < procs; i++)
    {
        if (pthread_create( &thrs[i], NULL, thread_routine1,
            (void *)(long)i ))
        {
            perror( "pthread_create" );
            procs = i;
            break;
        }
    }

    for (i = 0; i < procs; i++)
        pthread_join( thrs[i], NULL );

    printf("===== don't use pthread mutex =====\n");
    printf("After doing all the math, global_int value is: %d\n", global_int1 );
    printf("Expected value is: %d\n", INC_TO * procs );
    printf("Correct rate: %f%\n\n", (double)(((double)global_int1)/((double)(INC_TO * procs)) * 100));

    for (i = 0; i < procs; i++)
    {
        if (pthread_create( &thrs[i], NULL, thread_routine2,
            (void *)(long)i ))
        {
            perror( "pthread_create" );
            procs = i;
            break;
        }
    }

    for (i = 0; i < procs; i++)
        pthread_join( thrs[i], NULL );

    printf("===== use pthread mutex =====\n");
    printf("After doing all the math, global_int value is: %d\n", global_int2);
    printf("Expected value is: %d\n", INC_TO * procs );
    printf("Correct rate: %f%\n\n", (double)(((double)global_int2)/((double)(INC_TO * procs)) * 100));

    free(thrs);
    return 0;
}

jwwang@jwwang:~/test$ ./a.out 
Starting 4 threads...
proc_num :2,__sync_fetch_and_add cost 201870083 CPU cycle,cost 74471 us
proc_num :1,__sync_fetch_and_add cost 216505929 CPU cycle,cost 79872 us
proc_num :0,__sync_fetch_and_add cost 221643287 CPU cycle,cost 81767 us
proc_num :3,__sync_fetch_and_add cost 202669487 CPU cycle,cost 74767 us
===== use automic method =====
After doing all the math, global_int value is: 4000000
Expected value is: 4000000
Correct rate: 100.000000%

proc_num :0,__sync_fetch_and_add cost 22410118 CPU cycle,cost 8267 us
proc_num :1,__sync_fetch_and_add cost 29147387 CPU cycle,cost 10752 us
proc_num :3,__sync_fetch_and_add cost 29398320 CPU cycle,cost 10845 us
proc_num :2,__sync_fetch_and_add cost 11182123 CPU cycle,cost 4124 us
===== don't use pthread mutex =====
After doing all the math, global_int value is: 1789149
Expected value is: 4000000
Correct rate: 44.728725%

proc_num :0,pthread lock cost 875600915 CPU cycle,cost 323023 us
proc_num :3,pthread lock cost 905362503 CPU cycle,cost 334003 us
proc_num :1,pthread lock cost 926347504 CPU cycle,cost 341745 us
proc_num :2,pthread lock cost 938705022 CPU cycle,cost 346304 us
===== use pthread mutex =====
After doing all the math, global_int value is: 4000000
Expected value is: 4000000
Correct rate: 100.000000%

1 不加锁的情况下,不能返回正确的结果
  测试程序结果显示,正确结果为400万,实际为1789149
  每台机器不一样,当时肯定结果不正确

2 线程锁和原子性自加都能返回正确的结果。

3 性能上__sync_fetch_and_add,完爆线程锁。
  从测试结果上看, __sync_fetch_and_add,速度是线程锁的4倍
  机器不一样,结果也不一样,当时可定比线程锁好
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值