這是我目前正在閱讀的 OSTEP 的 Sloppy Counter 實作代碼,有一些我不明白的地方
假設以下代碼在 4 核 CPU 上運行
typedef struct __counter_t {
int global; // global count
pthread_mutex_t glock; // global lock
int local[NUMCPUS]; // local count (per cpu)
pthread_mutex_t llock[NUMCPUS]; // ... and locks
int threshold; // update frequency
}counter_t;
// init: record threshold, init locks, init values
// of all local counts and global count
void init(counter_t* c, int threshold) {
c->threshold = threshold;
c->global = 0;
pthread_mutex_init(&c->glock, NULL);
int i;
for (i = 0; i < NUMCPUS; i ) {
c->local[i] = 0;
pthread_mutex_init(&c->llock[i], NULL);
}
// update: usually, just grab local lock and update local amount
// once local count has risen by ‘threshold’, grab global
// lock and transfer local values to it
void update(counter_t* c, int threadID, int amt) {
pthread_mutex_lock(&c->llock[threadID]);
c->local[threadID] = amt; // assumes amt > 0
if (c->local[threadID] >= c->threshold) { // transfer to global
pthread_mutex_lock(&c->glock);
c->global = c->local[threadID];
pthread_mutex_unlock(&c->glock);
c->local[threadID] = 0;
}
pthread_mutex_unlock(&c->llock[threadID]);
}
// get: just return global amount (which may not be perfect)
int get(counter_t* c) {
pthread_mutex_lock(&c->glock);
int val = c->global;
pthread_mutex_unlock(&c->glock);
return val; // only approximate!
}
為什么每個本地柜臺都必須有一個鎖__counter_t?在update()函式中,執行緒的 id 作為引數傳入,這是否意味著只有一個執行緒可以訪問local[threadID]?如果發生背景關系切換,則其他執行緒將僅訪問local[threadID]與其 threadID 對應的執行緒。我不明白為什么在訪問它們自己的執行緒之前必須鎖定執行緒,local[NUMCPUS]因為陣列中的每個元素都不會被它們自己的其他執行緒訪問,并且沒有其他執行緒會update()使用相同的 threadID呼叫
uj5u.com熱心網友回復:
為什么每個本地計數器都必須有一個鎖
參考這本書
除了這些計數器之外,還有鎖:每個本地計數器1一個,全域計數器一個。
1是什么意思?在頁面末尾:
1我們需要本地鎖,因為我們假設每個核心上可能有多個執行緒。相反,如果每個核心上只運行一個執行緒,則不需要本地鎖。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/523274.html
標籤:C多线程线程安全线程
