如何在使用多线程时检测数据丢失的位置

时间:2015-11-16 06:54:23

标签: c linux multithreading operating-system pthreads

我有一个程序,允许多个线程将条目插入哈希表并检索它们。哈希表本身是一个非常简单的实现,其中包含定义每个桶条目的结构和用于保存每个桶的表(数组)。我非常喜欢并发和多线程,但我认为为了避免数据在插入和读取操作期间丢失在表中,需要添加某种同步(以互斥锁的形式)避免另一个进程对一个进程的数据操作进行抢占。

在实践中,我不确定如何判断进程可以在哈希表上的数据读取或写入操作中被抢占的位置以及应该放置何种锁以避免此类问题以及死锁。根据{{​​3}}网站,对于哈希表插入方法,我在每个键插入表中之前添加了一个互斥锁,并在函数末尾解锁它。我基本上在函数中执行类似的操作,我从哈希表中读取数据,当我运行代码时,似乎最初成功插入了键,但是当应该检索键时程序挂起。以下是我为每个函数实现锁定的方法:

// Inserts a key-value pair into the table
void insert(int key, int val) {
    pthread_mutex_lock(&lock);
    int i = key % NUM_BUCKETS;
    bucket_entry *e = (bucket_entry *) malloc(sizeof(bucket_entry));
    if (!e) panic("No memory to allocate bucket!");
    e->next = table[i];
    e->key = key;
    e->val = val;
    table[i] = e;
    pthread_mutex_unlock(&lock);
    pthread_exit(NULL);
}

// Retrieves an entry from the hash table by key
// Returns NULL if the key isn't found in the table
bucket_entry * retrieve(int key) {
    pthread_mutex_lock(&lock);
    bucket_entry *b;
    for (b = table[key % NUM_BUCKETS]; b != NULL; b = b->next) {
        if (b->key == key) return b;
    }
    pthread_mutex_unlock(&lock);
    pthread_exit(NULL);
    return NULL;
}

所以这里的主要问题是:

  1. 如何判断每个线程操作之间数据丢失的位置

  2. 从哈希表中检索密钥会导致程序挂起的原因是什么?

1 个答案:

答案 0 :(得分:3)

首先,您应该阅读有关pthreads的更多信息。另请阅读pthreads(7)。请特别注意,pthread_mutex_lock之类的每个锁定调用都应始终,然后在相同的互斥锁上调用pthread_mutex_unlock(和通常你应该采用纪律,每个锁定和解锁都发生在相同的块中。因此,return的{​​{1}}循环中的for错误,您应该编码:

retrieve

然后,您可以使用valgrind并使用最近的 GCC编译器(例如2015年11月的5.2)。编译所有警告&调试信息(bucket_entry * retrieve(int key) { bucket_entry *res = NULL; pthread_mutex_lock(&lock); for (bucket_entry *b = table[key % NUM_BUCKETS]; b != NULL; b = b->next) { if (b->key == key) { res = b; break; }; } pthread_mutex_unlock(&lock); return res; } )。阅读有关清洁剂debugging options的信息,特别要考虑使用gcc -Wall -Wextra -g -pthread

调用-fsanitize=thread几乎没有理由(同样,你很少在程序中调用pthread_exit)。当你这样做时,整个当前线程将被终止。