当前位置:网站首页>懒惰计数器 Lazy Counter
懒惰计数器 Lazy Counter
2022-06-09 06:01:00 【小北和小文】
现代计算机的多处理器结构催生出一系列并发程序,为了更好地在多处理器上运行,要利用锁的机制,保护临界区,避免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;
}
运行效果如下:

边栏推荐
- Topic24——3. 无重复字符的最长子串
- Divide by Zero 2017 and Codeforces Round #399 (Div. 1 + Div. 2, combined) C. Jon Snow and his Favou
- fatal: repository not found
- El table scroll bar style
- Entity to map tool
- 测试和线程
- 关于用vsCode格式化代码时,代码自动换行问题
- Google colab tips
- 【论文】CBAM: Convolutional Block Attention Module
- Topic24——3. Longest substring without duplicate characters
猜你喜欢
随机推荐
关于用vsCode格式化代码时,代码自动换行问题
Educational Codeforces Round 20 E. Roma and Poker
MVCC多版本控制
Complete webrtc video recording in five minutes
Parallels Desktop 安装 Windows10 提示“安全启动功能防止操作系统启动”解决方法
Image processing feature fusion correlation extension
unity 定位服务GPS API
[early spring 2022] [leetcode] 91 Decoding method
Topic25——4. 寻找两个正序数组的中位数
VK Cup 2017 - Round 2 A. Voltage Keepsake
Here comes the era of metaltc2.0
How to monitor JVM GC
Testing and threading
Record TCP time once_ Blood cases caused by wait
Divide by Zero 2017 and Codeforces Round #399 (Div. 1 + Div. 2, combined) D. Jon and Orbs
Thread interrupted detailed parsing
C entrustment related
C# 迭代器
If you become a qualified technical manager
Jdbc-dbutils








