无锁编程(三) - 忙等待
概念
忙等待可以认为是一种特殊的忙等待
忙等待分类
Peterson算法
xchg解法
TSL解法
自旋锁
Peterson算法
Peterson算法是一个实现互斥锁的并发程序设计算法,可以控制两个线程访问一个共享的单用户资源而不发生访问冲突。GaryL. Peterson于1981年提出此算法。
#include <stdio.h> #include <pthread.h> #include <stdlib.h> #include <sys/types.h> #include <sys/time.h> #include <stdint.h> int count = 0; #define N 2 volatile int turn; volatile int interested[N] = {0}; void enter_region(int process) { int other = 1 - process; //另一个进程 interested[process] = true; turn = process; while (turn == process && interested[other] == true) NULL; //一直循环,直到other进程退出临界区 } void leave_region(int process) { interested[process] = false; // leave critical region } void *test_func(void *arg) { int process = *((int *)arg); printf("thread %d run\n", process); int i=0; for(i=0;i<2000000;++i) { enter_region(process); //printf("%d enter, count = %d\n", pthread_self(),count); ++count; leave_region(process); } return NULL; } int main(int argc, const char *argv[]) { pthread_t id[N]; int process[N]; int i = 0; uint64_t usetime; struct timeval start; struct timeval end; gettimeofday(&start,NULL); for(i=0;i<N;++i) { process[i] = i; } for(i=0;i<N;++i) { pthread_create(&id[i],NULL,test_func,&process[i]); } for(i=0;i<N;++i) { pthread_join(id[i],NULL); } gettimeofday(&end,NULL); usetime = (end.tv_sec-start.tv_sec)*1000000+(end.tv_usec-start.tv_usec); printf("count = %d, usetime = %lu usecs\n", count, usetime); return 0; }
结果说明:
[root@rocket lock-free]#./busywait_peterson
thread 0 run
thread 1 run
count = 3999851, usetime = 263132 usecs
可以看出,虽然是互斥算法,但是实测的结果缺不是十分精确,有少量的count丢失,这点让人感到很差异,这里先不去深究,有经验的同学可以帮忙分析一下原因。
xchg解法
#include <stdio.h> #include <pthread.h> #include <stdlib.h> #include <sys/types.h> #include <asm/system.h> #include <sys/time.h> #include <stdint.h> volatile int in_using = 0; int count = 0; #define N 2 void enter_region() { while (xchg(&in_using, 1)) NULL; } void leave_region() { in_using = 0; // leave critical region } void *test_func(void *arg) { int i=0; for(i=0;i<2000000;++i) { enter_region(); ++count; leave_region(); } return NULL; } int main(int argc, const char *argv[]) { pthread_t id[20]; int i = 0; uint64_t usetime; struct timeval start; struct timeval end; gettimeofday(&start,NULL); for(i=0;i<N;++i) { pthread_create(&id[i],NULL,test_func,NULL); } for(i=0;i<N;++i) { pthread_join(id[i],NULL); } gettimeofday(&end,NULL); usetime = (end.tv_sec-start.tv_sec)*1000000+(end.tv_usec-start.tv_usec); printf("count = %d, usetime = %lu usecs\n", count, usetime); return 0; }
结果说明:这个结果自然是非常精确,感觉比peterson算法靠谱多了,性能倒是差别不大。
[root@rocket lock-free]# ./busywait_xchg
count = 4000000, usetime = 166548 usecs
TSL解法(Test and Set Lock)
enter_region:
tsl register, lock |复制lock到寄存器,并将lock置为1
cmp register, #0 | lock等于0吗?
jne enter_region |如果不等于0,已上锁,再次循环
ret |返回调用程序,进入临界区
leave_region:
move lock, #0 |置lock为0
ret |返回调用程序
自旋锁
自旋锁请参考我的另一篇文章,这里不再赘述。
http://www.cnblogs.com/linuxbug/p/4840152.html
版权声明:本文为博主原创文章,未经博主允许不得转载。