Multithreading 跳过列表中的细粒度锁定

Multithreading 跳过列表中的细粒度锁定,multithreading,locking,pthreads,skip-lists,Multithreading,Locking,Pthreads,Skip Lists,我正在尝试使用细粒度锁定机制在c中实现基于锁的skiplist。在运行代码时,应用的锁定机制似乎是粗粒度的。我使用节点结构中定义的pthread_mutex_t lock变量在前面的节点中设置了锁,以便插入,并在使用后释放它们。整个列表并没有被锁定,只是节点被锁定了,它似乎仍然在实现粗粒度的锁定机制。下面提供了完成锁定机制的代码片段。实现错误吗 for(level = 0; valid && (level <=topLevel); level++){

我正在尝试使用细粒度锁定机制在c中实现基于锁的skiplist。在运行代码时,应用的锁定机制似乎是粗粒度的。我使用节点结构中定义的pthread_mutex_t lock变量在前面的节点中设置了锁,以便插入,并在使用后释放它们。整个列表并没有被锁定,只是节点被锁定了,它似乎仍然在实现粗粒度的锁定机制。下面提供了完成锁定机制的代码片段。实现错误吗

for(level = 0; valid && (level <=topLevel); level++){
            pred = preds[level];
            succ = succs[level];

            if(pred != prevPred){
                pthread_mutex_lock(pred -> lock);
                highestLocked   = level;
                prevPred        = pred;
            }

            valid = !(pred -> marked) && !(succ -> marked) && (pred -> next[level] == succ);
        }
        if(!valid){
            for(level = 0;level <= highestLocked; level++)
                pthread_mutex_unlock(preds[level] -> lock);
            continue;
        }
        newNode = createNewNode(x -> val, topLevel);
        for(level = 0; level <= topLevel; level++){
            newNode -> next[level] = succs[level];
            preds[level] -> next[level] = newNode;
        }
        newNode -> fullyLinked = 1;
        for(level = 0;level <= highestLocked; level++)
                pthread_mutex_unlock(preds[level] -> lock);
编辑: 将节点插入skiplist的代码

int add(Node *x, int *preval){
    int lFound, highestLocked, valid, level;
    Node *nodeFound, *pred, *succ, *prevPred, *newNode;
    // int topLevel = randomLevel(MAX_LEVEL);
    int topLevel = (rand()%MAX_LEVEL)+1;
    *preval=topLevel;
    Node **preds = (Node **)malloc(sizeof(Node *) * (MAX_LEVEL + 1));//predecessor list
    Node **succs = (Node **)malloc(sizeof(Node *) * (MAX_LEVEL + 1));//successor list
    while(1){
        lFound = find(x, preds, succs);//gets predecessor and successor list of node where x to be inserted
        if(lFound != -1){
            nodeFound = succs[lFound];
            if(!nodeFound->marked){
                while(!nodeFound->fullyLinked){;}
                return 0;
            }
            continue;
        }
        highestLocked   = -1;
        prevPred        = NULL;
        valid           = 1;
        for(level = 0; valid && (level <=topLevel); level++){
            pred = preds[level];
            succ = succs[level];
            //locking the predecessor node level
            if(pred != prevPred){
                pthread_mutex_lock(pred -> lock);
                highestLocked   = level;
                prevPred        = pred;
            }

            valid = !(pred -> marked) && !(succ -> marked) && (pred -> next[level] == succ);
        }
        //releasing locked nodes
        if(!valid){
            for(level = 0;level <= highestLocked; level++)
                pthread_mutex_unlock(preds[level] -> lock);
            continue;
        }
        newNode = createNewNode(x -> val, topLevel);
        for(level = 0; level <= topLevel; level++){
            newNode -> next[level] = succs[level];
            preds[level] -> next[level] = newNode;
        }
        newNode -> fullyLinked = 1;
        //releasing locked nodes
        for(level = 0;level <= highestLocked; level++)
                pthread_mutex_unlock(preds[level] -> lock);
        return 1;
    }   
}
int添加(节点*x,int*preval){
int lFound,highestLocked,valid,level;
Node*nodeFound、*pred、*succ、*prevPred、*newNode;
//int topLevel=随机水平(最大水平);
int topLevel=(rand()%MAX_LEVEL)+1;
*preval=顶级;
节点**preds=(节点**)malloc(节点*)*(最大级别+1));//前置列表
节点**成功=(节点**)malloc(节点*的大小*(最大级别+1));//后续列表
而(1){
lFound=find(x,preds,succs);//获取要插入x的节点的前置和后续列表
如果(lFound!=-1){
nodeFound=succs[lFound];
如果(!nodeFound->已标记){
而(!nodeFound->fullyLinked){;}
返回0;
}
继续;
}
highestLocked=-1;
prevPred=NULL;
有效=1;
对于(级别=0;有效&&(级别锁定);
最高锁定=水平;
prevPred=pred;
}
有效=!(预定->已标记)&&!(成功->已标记)&&(预定->下一个[级别]==成功);
}
//释放锁定的节点
如果(!有效){
用于(标高=0;标高锁);
继续;
}
newNode=createNewNode(x->val,顶级);
for(级别=0;下一级[级别]=成功[级别];
preds[level]>next[level]=newNode;
}
newNode->fullyLinked=1;
//释放锁定的节点
用于(标高=0;标高锁);
返回1;
}   
}

想想什么数据被“细粒度”锁定。你正在锁定对skiplist内部列表的访问。访问这些列表对于任何线程在skiplist中搜索都是必要的。在for循环的第一次迭代中(假设pred!=prevpre),您将锁定0级的pred->lock。因此,每个线程将尝试通过skiplist在同一时间获取相同的锁


我建议找一本“多处理器编程的艺术”,第14章讨论了skiplist。

锁定机制只针对要插入新数据的节点的前置列表,因此,当在以后的会话中插入新节点时,我想k个线程可以进入skiplist。一旦插入结束,在前置节点级别上释放锁,以便其他线程可以使用新节点。我已经在编辑部分发布了完整的代码供您参考
int add(Node *x, int *preval){
    int lFound, highestLocked, valid, level;
    Node *nodeFound, *pred, *succ, *prevPred, *newNode;
    // int topLevel = randomLevel(MAX_LEVEL);
    int topLevel = (rand()%MAX_LEVEL)+1;
    *preval=topLevel;
    Node **preds = (Node **)malloc(sizeof(Node *) * (MAX_LEVEL + 1));//predecessor list
    Node **succs = (Node **)malloc(sizeof(Node *) * (MAX_LEVEL + 1));//successor list
    while(1){
        lFound = find(x, preds, succs);//gets predecessor and successor list of node where x to be inserted
        if(lFound != -1){
            nodeFound = succs[lFound];
            if(!nodeFound->marked){
                while(!nodeFound->fullyLinked){;}
                return 0;
            }
            continue;
        }
        highestLocked   = -1;
        prevPred        = NULL;
        valid           = 1;
        for(level = 0; valid && (level <=topLevel); level++){
            pred = preds[level];
            succ = succs[level];
            //locking the predecessor node level
            if(pred != prevPred){
                pthread_mutex_lock(pred -> lock);
                highestLocked   = level;
                prevPred        = pred;
            }

            valid = !(pred -> marked) && !(succ -> marked) && (pred -> next[level] == succ);
        }
        //releasing locked nodes
        if(!valid){
            for(level = 0;level <= highestLocked; level++)
                pthread_mutex_unlock(preds[level] -> lock);
            continue;
        }
        newNode = createNewNode(x -> val, topLevel);
        for(level = 0; level <= topLevel; level++){
            newNode -> next[level] = succs[level];
            preds[level] -> next[level] = newNode;
        }
        newNode -> fullyLinked = 1;
        //releasing locked nodes
        for(level = 0;level <= highestLocked; level++)
                pthread_mutex_unlock(preds[level] -> lock);
        return 1;
    }   
}