最近由于项目需要,需要将原先使用的icu4c由4.x版本升级到5.x,但是利用编译好的5.x版本的icu4c链接库编译原先的程序时,报出了类似undefined __sync_sub_and_fetch的错误,没办法,最后通过查看icu4c的源码,加入了一些编译选项,将相关的__sync_xxxx函数默认不使用。
虽然问题解决了,但是第一次接触到__sync_xxx类型的函数,还是想弄明白它的作用。后来发现这一类函数非常有用,尤其是在做多线程的无锁化操作时,它感觉就相当与内核里面使用的atomic_t。
__sync_fetch_and_add系列一共有十二个函数,有加/减/与/或/异或/等函数的原子性操作函数, __sync_fetch_and_add, 顾名思义,现fetch,然后自加,返回的是自加以前的值。以count = 4为例,调用__sync_fetch_and_add(&count,1),之后,返回值是4,然后,count变成了5.
在用gcc编译的时候要加上选项 -march=i686(后来发现并不是所有的环境下编译都需要加这个,比如,在我的Ubuntu 12.04 Intel处理器的环境下,不许要加这个参数)
type __sync_fetch_and_add (type *ptr, type value); type __sync_fetch_and_sub (type *ptr, type value); type __sync_fetch_and_or (type *ptr, type value); type __sync_fetch_and_and (type *ptr, type value); type __sync_fetch_and_xor (type *ptr, type value); type __sync_fetch_and_nand (type *ptr, type value); type __sync_add_and_fetch (type *ptr, type value); type __sync_sub_and_fetch (type *ptr, type value); type __sync_or_and_fetch (type *ptr, type value); type __sync_and_and_fetch (type *ptr, type value); type __sync_xor_and_fetch (type *ptr, type value); type __sync_nand_and_fetch (type *ptr, type value);
自己也写了一个小的测试程序,验证使用这一类函数和普通线程锁的效率对比
#include <stdio.h> #include <unistd.h> #include <pthread.h> #include <stdlib.h> #include <sys/time.h> int global_int = 0; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; void* thread_func(void *arg) { int i; for (i = 0; i < 1000000; i++) { #ifdef WITH_MUTEX pthread_mutex_lock(&mutex); global_int++; pthread_mutex_unlock(&mutex); #elif defined WITH_ATOMIC __sync_add_and_fetch(&global_int, 1); #else global_int++; #endif } } int main() { struct timeval start_time, end_time; gettimeofday(&start_time, NULL); int proc, i; proc = sysconf(_SC_NPROCESSORS_ONLN); if (proc < 0) exit(1); pthread_t *threadId = (pthread_t *)malloc(proc*sizeof(pthread_t)); for (i = 0; i < proc; i++) { pthread_create(&threadId[i], NULL, thread_func, NULL); } for (i = 0; i < proc; i++) { pthread_join(threadId[i], NULL); } gettimeofday(&end_time, NULL); printf("thread number = %d global_int = %d cost time msecond = %ld\n", proc, global_int, (long)((end_time.tv_sec - start_time.tv_sec)*1000 + (end_time.tv_usec - start_time.tv_usec)/1000)); }
使用这一类函数,不许要包含特殊的头文件,编译如下:
gcc -DWITH_ATOMIC -o test test.c -pthread运行结果:
thread number = 4 global_int = 4000000 cost time msecond = 133
而如果使用普通的线程锁,运行结果如下:
thread number = 4 global_int = 4000000 cost time msecond = 526