了解链接列表中的锁定

时间:2019-05-30 19:08:05

标签: c linked-list pthreads locks

我现在正在学习有关互斥锁和多线程数据结构的知识。我正在尝试实现一个并发排序的链表数据结构,该结构支持插入,删除,打印和释放整个列表,并且我已经编写了所有功能。不幸的是,我对线程锁的概念还很陌生。我尝试使用移交锁定实现排序后的链表,但是元素的插入和删除均不起作用(我在Red Hat VM上尝试了这些功能),而且我也不知道print功能是否正确。在Linux上调试时遇到问题,因为我还很陌生。有什么建议可以更正我的代码吗?请注意,我正在寻找有关如何以最佳方式实现越区切换手动锁定的说明,而不是将整个代码作为答案。 提前致谢。

concurrent_list.h:

函数和结构声明的头文件。

 typedef struct node node;
  typedef struct list list;

  list* create_list();
  void delete_list(list* list);
  void print_list(list* list);
  void insert_value(list* list, int value);
  void remove_value(list* list, int value);
  void count_list(list* list, int (*predicate)(int));

concurrent_list.c

该文件执行的头文件中的功能和 还有更多功能。

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "concurrent_list.h"

struct node {
  int value;
  node* next;
  pthread_mutex_t lock; // hand over hand implies a lock for every node
};

struct list {
  node* head;
};

// print the value of a node
void print_node(node* node)
{
  if(node)
  {
    printf("%d ", node->value);
  }
}

// create  a new empty list
list* create_list()
{
  list* new_list = (list*)malloc(sizeof(list));

  if(new_list == NULL)
  {
    return NULL;
  }

  new_list->head = NULL;

  return new_list;
}

// delete the entire list (lock the current element for other threads)
void delete_list(list* list)
{
  node* temp = list->head;
  node* curr;

  if(temp == NULL) return;

   while (temp != NULL)
   {
       pthread_mutex_lock(&(temp->lock));
       curr = temp;
       free(curr);
       temp = temp->next;

   }
}

// insert function for a new value if a value already exists then do nothing
// lock the current and previous elements for other threads
void insert_value(list* list, int value)
{
    if(list == NULL) return;

    node* new_node = (node*)malloc(sizeof(node));

    if(new_node == NULL) return;

    new_node->value = value;

    if(list->head == NULL)
    {
        list->head = new_node;
        list->head->next = NULL;
    }

    node* prev = list->head;
    pthread_mutex_lock(&prev->lock);

    node* curr = prev->next;

    if(curr == NULL)
    {
        if(prev->value > value)
        {
            new_node->next = prev;
            prev->next == NULL;
        }

        else if(prev->value < value)
        {
            prev->next = new_node;
            new_node->next = NULL;
        }

        else
        {
            free(new_node);
        }

        pthread_mutex_unlock(&prev->lock);

        return;
    }

    pthread_mutex_lock(&curr->lock);

    while(curr->value < value)
    {
      pthread_mutex_unlock(&prev->lock);
      prev = curr;
      curr = prev->next;

      if(curr == NULL)
      {
        pthread_mutex_unlock(&prev->lock);
        return;
      }

      pthread_mutex_lock(&curr->lock);
    }

    if(curr->value == value)
    {
       pthread_mutex_unlock(&curr->lock);
       pthread_mutex_unlock(&prev->lock);
       return;
    }

    new_node->next = curr;
    prev->next = new_node;
    pthread_mutex_unlock(&curr->lock);
    pthread_mutex_unlock(&prev->lock);
}

//delete the first appearance of a value in the list if it exists in the list
// lock the current and previous elements for other threads
void remove_value(list* list, int value)
{
    if(list == NULL || list->head == NULL) return;

    node* prev = list->head;
    pthread_mutex_lock(&prev->lock);

    node* curr = prev->next;

    if(curr == NULL)
    {
        if(prev->value == value)
        {
            prev->next == NULL;
        }

        pthread_mutex_unlock(&prev->lock);

        return;
    }

    pthread_mutex_lock(&curr->lock);

    while(curr->value < value)
    {
      pthread_mutex_unlock(&prev->lock);
      prev = curr;
      curr = prev->next;

      if(curr == NULL)
      {
        pthread_mutex_unlock(&prev->lock);
        return;
      }

      pthread_mutex_lock(&curr->lock);
    }

    if(curr->value == value)
    {
        prev->next = curr->next;
    }
    pthread_mutex_unlock(&curr->lock);
    pthread_mutex_unlock(&prev->lock);
}

//print the entire list
// lock the current element for other threads
void print_list(list* list)
{
  node* curr = list->head;

  while(curr != NULL)
  {
      pthread_mutex_lock(&curr->lock);
      print_node(curr);
      pthread_mutex_unlock(&curr->lock);
      curr = curr->next;
  }
  printf("\n");
}

// print how many nodes in the list satisfy a given predicate function
// lock the current element for other threads
void count_list(list* list, int (*predicate)(int))
{
  int count = 0;
  node* curr = list->head;

  while(curr != NULL)
  {
      pthread_mutex_lock(&curr->lock);

      if(predicate(curr->value))
      {
          count++;
      }

      pthread_mutex_unlock(&curr->lock);

      curr = curr->next;
  }

  printf("%d items were counted\n", count);
}

0 个答案:

没有答案