懒惰计数器 Lazy Counter

现代计算机的多处理器结构催生出一系列并发程序,为了更好地在多处理器上运行,要利用锁的机制,保护临界区,避免race condition导致程序出错。

因此锁的思想在整个并发编程中都比较适用,在更新critical section的时候先请求锁,更新完再释放。并发计数器也是同样的思想,只是为了更好利用多处理器、提高扩展性,并发计数器中以懒惰计数器为著名。

全局计数器维护真正的全局值,但是各个cpu上都运行着一个局部的计数器,局部之间自我通信,速度快到媲美单核性能(单个速度,多个局部加起来那就是单核的许多倍了)。只有当局部计数器达到一定的阈值时才会更新全局计数器。

 代码如下 C语言 Linux下编译:gcc -pthread lazycount.c -o lazycount.out  运行:./lazycount.out

#include <pthread.h>
#include <stdio.h>
#include <assert.h>
#include <stdlib.h> /*srand && random*/
#include <time.h> /*time()*/
//懒惰计数器 可扩展性强 局部具有自己的锁 全局具有自己的全局锁
#define NUMOFCPU 40

#define COUNTERTIME 1000000

typedef struct counter_t {
    int global;
    pthread_mutex_t glock;
    int local[NUMOFCPU];    //维系局部的统计值
    pthread_mutex_t llock[NUMOFCPU];    //各个局部含有一个锁
    int threshold;  //局部向全局更新阈值
} counter_t ;

counter_t *lazy;//生命一个全局counter 创建多个线程来操作它

void init(counter_t *c, int threshold);

void update(counter_t *c, int tid,int amt);

int get (counter_t *c);

void * mythread(void * arg) ;


int main(int argc, char *argv[]) {
	srand((unsigned int) time(NULL));
    lazy = (counter_t *)malloc(sizeof(counter_t));
    init(lazy, 1000);
    pthread_t p[NUMOFCPU];
    for(int i = 0; i < NUMOFCPU; i++) {
        pthread_create(&p[i], NULL, mythread, &i);
    }
     for(int i = 0; i < NUMOFCPU; i++) {
        pthread_join(p[i], NULL);
    }
    printf("global is %d\n", lazy->global);
}

void * mythread(void * arg) {
    int *tid = (int *) (arg);
    int temp = 0;
    //进行计数
    for(int i = 0; i < COUNTERTIME; i++) {
        temp = random() % 17;
        update(lazy, *tid, temp);
    }
}



//init 为全局和局部都设置自己的锁
void init(counter_t *c, int threshold) {
    c->global = 0;
    assert(pthread_mutex_init(&c->glock, NULL)==0);
    for(int i = 0; i < NUMOFCPU; i++) {
         c->local[i] = 0;
         assert(pthread_mutex_init(&c->llock[i], NULL) == 0);
    }
    c->threshold = threshold;
}


//update 更新指定pid线程局部的值 如果到达阈值则更新全局的值
void update(counter_t *c, int tid,int amt) {
    pthread_mutex_lock(&c->llock[tid]);
    c->local[tid] += amt;
	printf("Local Update : %d \n", amt);
    if(c->local[tid] >= c->threshold) {
        pthread_mutex_lock(&c->glock);
        c->global += c->local[tid];
		printf("Global Update : %d \n", c->local[tid]);
        pthread_mutex_unlock(&c->glock);
        c->local[tid] = 0;//局部置零
    }
    pthread_mutex_unlock(&c->llock[tid]);
}

//get 获取global值
int get (counter_t *c) {
    pthread_mutex_lock(&c->glock);
    int val = c->global;
    pthread_mutex_unlock(&c->glock);
    return val;
}




 运行效果如下:

 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值