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

    RCURead-Copy Update

    RCU就是指读-拷贝修改,它是基于其原理命名的。对于被RCU保护的共享数据结构,读操作不需要获得任何锁就可以访问,但写操作在访问它时首先拷贝一个副本,然后对副本进行修改,最后在适当的时机把指向原来数据的指针重新指向新的被修改的数据。这个时机就是所有引用该数据的CPU都退出对共享数据的操作。

    Linux内核中内存管理大量的运用到了RCU机制。为每个内存对象增加了一个原子计数器用来继续该对象当前访问数。当没有其他进程在访问该对象时(计数器为0),才允许回收该内存。

    从这个流程可以看出,RCU类似于一种读写锁的优化,用于解决读和写之间的同步问题。比较适合读多,写少的情况,当写操作过多的时候,这里的拷贝和修改的成本同样也很大。(写操作和写操作之间的同步还需要其它机制来保证)。

     

    代码讲解:

    #include <stdio.h>
    #include <pthread.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <string.h>
    
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
    int currentidx = 0;
    char* str[2] = {0};
    
    void* consume(void *arg)
    {
        sleep(1);
        while(1)
        {
            printf("************************consumed %s, index %d, self %d
    ",str[currentidx], currentidx, pthread_self());
            sleep(1); 
        }
        
        return NULL;
    }
    
    void* produce( void * arg )
    {
        const char* s_str1 = "hello";
        const char* s_str2 = "world";
    	
        while(1)
        {
    	printf("product begin
    ");
    		
    	// read copy
            int other = 1 - currentidx;
    	str[other] = (char*)malloc(6);
    	if (other == 0)
    	{
    		strncpy(str[other], s_str1, 6);
    	}
    	else
    	{
    		strncpy(str[other], s_str2, 6);
    	}
    		
    	// update原子的修改索引
    	currentidx = other;
    	// delete old currentidx
    	free(str[1-currentidx]);
            sleep(5);
        }
        
        return NULL;
    }
    
    int main( void )
    {
        pthread_t thread1,thread2;
        pthread_create(&thread1, NULL, &produce, NULL );
        pthread_create(&thread2, NULL, &consume, NULL );
        pthread_join(thread1,NULL);
        pthread_join(thread2,NULL);
        return 0;
    }
    

    结果说明:

    [root@rocket lock-free]# ./lockfree_rcu

    product begin

    ************************consumed world, index1, self 1395513088

    ************************consumed world, index1, self 1395513088

    ************************consumed world, index1, self 1395513088

    ************************consumed world, index1, self 1395513088

    product begin

    ************************consumed hello, index0, self 1395513088

    ************************consumed hello, index0, self 1395513088

    ************************consumed hello, index0, self 1395513088

    ************************consumed hello, index0, self 1395513088

    ************************consumed hello, index0, self 1395513088

    product begin

    ************************consumed world, index1, self 1395513088

    ************************consumed world, index1, self 1395513088

    ************************consumed world, index1, self 1395513088

    ************************consumed world, index1, self 1395513088

    ************************consumed world, index1, self 1395513088

     


     

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

  • 相关阅读:
    toString()和toLocaleString()有什么区别
    解决浏览器跨域问题
    JavaScript排序,不只是冒泡
    input disabled的情况下在IOS设备中怎么修改颜色
    jquery api 中文文档
    javascript中var that=this的意思
    JS中(function(){xxx})(); 这种写法的意思
    http-equiv 的使用
    $(function(){......})的意思
    js中(function(){…})()立即执行函数写法理解
  • 原文地址:https://www.cnblogs.com/linuxbug/p/4840140.html
Copyright © 2011-2022 走看看