zoukankan      html  css  js  c++  java
  • 无锁编程(三)

    概念

    忙等待可以认为是一种特殊的忙等待

     

    忙等待分类

    Peterson算法

    xchg解法

    TSL解法

    自旋锁

     

    Peterson算法

    Peterson算法是一个实现互斥锁的并发程序设计算法,可以控制两个线程访问一个共享的单用户资源而不发生访问冲突。GaryL. Peterson1981年提出此算法。

    #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
    ", process);
    	int i=0;
    	for(i=0;i<2000000;++i)
    	{
    		enter_region(process);
    		//printf("%d enter, count = %d
    ", 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
    ", 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
    ", 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 |lock0

    ret |返回调用程序

     

    自旋锁

    自旋锁请参考我的另一篇文章,这里不再赘述。

    http://www.cnblogs.com/linuxbug/p/4840152.html

     版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 相关阅读:
    PHP静态页生成
    svn部署web项目
    Nginx出现403 forbidden
    Node-red的基础使用——inject/debug/function的使用(1)
    功能/性能测试报告的编写格式及模板
    node-red在不同环境安装步骤
    node-red实现接口自动化测试——初步认识
    docker删除image
    django测试开发,例一个接口的开发逻辑
    django测试平台开发,登录,验证,退出
  • 原文地址:https://www.cnblogs.com/linuxbug/p/4840143.html
Copyright © 2011-2022 走看看