__sync_fetch_and_add,pthread_mutex_lock
2017-07-10 18:00
246 查看
线程安全
#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倍 机器不一样,结果也不一样,当时可定比线程锁好
相关文章推荐
- linux无锁化编程--__sync_fetch_and_add系列原子操作函数
- 安装Redis报错:undefined reference to `__sync_add_and_fetch_4'
- 嵌入式 __sync_fetch_and_add系列函数
- __sync_fetch_and_add系列
- linux无锁化编程--__sync_fetch_and_add系列原子操作函数
- 多线程下变量-原子操作 __sync_fetch_and_add等等
- linux无锁化编程--__sync_fetch_and_add系列原子操作函数
- linux无锁化编程--__sync_fetch_and_add系列原子操作函数
- 线程下变量-原子操作 __sync_fetch_and_add
- 【Linux】多线程无锁编程--原子计数操作:__sync_fetch_and_add等12个操作
- 多线程条件下的计数器__原子的加/减 __sync_fetch_and_add
- linux无锁化编程--__sync_fetch_and_add系列原子操作函数
- 多线程下变量-原子操作 sync_fetch_and_add等等
- __sync_fetch_and_add系列的命令
- 编译redis2.6.2报zmalloc.c:223: undefined reference to__sync_add_and_fetch_4′解决方法
- libmemcached安装undefined reference to `__sync_fetch_and_add_4'
- mingw编译x264 出错undefined reference to `__sync_add_and_fetch_4
- C/C++-------------__sync_fetch_and_add 原子操作------------------
- undefined references: __sync_fetch_and_add_4 and __sync_val_compare_and_swap_4
- Linux-Linux下安装redis报错"undefined reference to__sync_add_and_fetch_4"解决办法