C 中细粒度的线程安全链表
threads safe linked list fine grained in C
我正在实现一个具有细粒度锁定的链表,这意味着每个节点都有一个锁。
当我添加一个新节点时,我只想传递 2 个参数:键和值。
如何确保每个节点都有不同的锁?锁由pthread_mutex_t
.
实现
这是我要添加的实现:
int setos_add(int key, void* value)
{
volatile setos_node* node = head;
volatile setos_node* prev;
pthread_mutex_t new_mutex; //wrong: it will put the same lock to everyone
//lock the head node
if(pthread_mutex_lock(&(node->mutex)) == 0){
printf("failed locking\n");
exit(1);
}
// go through nodes until the key of "node" exceeds "key"
// new node should then be between "prev" and "node"
while ((node != NULL) && (node->key < key)) {
prev = node; //already locked
node = node->next;
//locking 2 nodes each time
if (node != NULL){
if(pthread_mutex_lock(&(node->mutex)) == 0){
printf("failed locking\n");
exit(1);
}
}
if (node -> key < key){ //else: we need also preve staying locked for the insertions
if (pthread_mutex_unlock(&(prev->mutex)) != 0){
printf("failed unlocking\n");
exit(1);
}
}
}
// if node is same as our key - key already in list
if ((node != NULL) && (node->key == key)){
if (node != NULL){ //not the end of the list
if (pthread_mutex_unlock(&(node->mutex)) != 0){
printf("failed unlocking\n");
exit(1);
}
}
if (prev != NULL){ //not the begining of the list
if (pthread_mutex_unlock(&(prev->mutex)) != 0){
printf("failed unlocking\n");
exit(1);
}
}
return 0;
}
// allocate new node and initialize it
setos_node* new_node = (setos_node*) malloc(sizeof(setos_node));
new_node->key = key;
new_node->value = value;
new_node->mutex = new_mutex; //to change
if(pthread_mutex_init(&(new_node-> mutex), NULL) != 0){
printf("failed init mutex");
exit(1);
}
// place node into list
new_node->next = node;
prev->next = new_node;
if (node != NULL){ //not the end of the list
if (pthread_mutex_unlock(&(node->mutex)) != 0){
printf("failed unlocking\n");
exit(1);
}
}
if (prev != NULL){ //not the begining of the list
if (pthread_mutex_unlock(&(prev->mutex)) != 0){
printf("failed unlocking\n");
exit(1);
}
}
return 1;
}
你可以看到在第三行我定义了 pthread_mutex_t
到节点。但是这样做,每个新节点都会有相同的pthread_mutex_t
吗?
我怎样才能做对?
是的,它将是同一个互斥量。
每次需要新的互斥量时,您都可以 malloc 一个新的互斥量元素,如下所示:
malloc(sizeof(pthread_mutex_t)))
像这样初始化:
pthread_mutex_init(m, NULL)
我正在实现一个具有细粒度锁定的链表,这意味着每个节点都有一个锁。
当我添加一个新节点时,我只想传递 2 个参数:键和值。
如何确保每个节点都有不同的锁?锁由pthread_mutex_t
.
这是我要添加的实现:
int setos_add(int key, void* value)
{
volatile setos_node* node = head;
volatile setos_node* prev;
pthread_mutex_t new_mutex; //wrong: it will put the same lock to everyone
//lock the head node
if(pthread_mutex_lock(&(node->mutex)) == 0){
printf("failed locking\n");
exit(1);
}
// go through nodes until the key of "node" exceeds "key"
// new node should then be between "prev" and "node"
while ((node != NULL) && (node->key < key)) {
prev = node; //already locked
node = node->next;
//locking 2 nodes each time
if (node != NULL){
if(pthread_mutex_lock(&(node->mutex)) == 0){
printf("failed locking\n");
exit(1);
}
}
if (node -> key < key){ //else: we need also preve staying locked for the insertions
if (pthread_mutex_unlock(&(prev->mutex)) != 0){
printf("failed unlocking\n");
exit(1);
}
}
}
// if node is same as our key - key already in list
if ((node != NULL) && (node->key == key)){
if (node != NULL){ //not the end of the list
if (pthread_mutex_unlock(&(node->mutex)) != 0){
printf("failed unlocking\n");
exit(1);
}
}
if (prev != NULL){ //not the begining of the list
if (pthread_mutex_unlock(&(prev->mutex)) != 0){
printf("failed unlocking\n");
exit(1);
}
}
return 0;
}
// allocate new node and initialize it
setos_node* new_node = (setos_node*) malloc(sizeof(setos_node));
new_node->key = key;
new_node->value = value;
new_node->mutex = new_mutex; //to change
if(pthread_mutex_init(&(new_node-> mutex), NULL) != 0){
printf("failed init mutex");
exit(1);
}
// place node into list
new_node->next = node;
prev->next = new_node;
if (node != NULL){ //not the end of the list
if (pthread_mutex_unlock(&(node->mutex)) != 0){
printf("failed unlocking\n");
exit(1);
}
}
if (prev != NULL){ //not the begining of the list
if (pthread_mutex_unlock(&(prev->mutex)) != 0){
printf("failed unlocking\n");
exit(1);
}
}
return 1;
}
你可以看到在第三行我定义了 pthread_mutex_t
到节点。但是这样做,每个新节点都会有相同的pthread_mutex_t
吗?
我怎样才能做对?
是的,它将是同一个互斥量。
每次需要新的互斥量时,您都可以 malloc 一个新的互斥量元素,如下所示:
malloc(sizeof(pthread_mutex_t)))
像这样初始化:
pthread_mutex_init(m, NULL)