无锁有序链表可以保证元素的唯一性,使其可用于哈希表的桶,甚至直接作为一个效率不那么高的map。普通链表的无锁实现相对简单点,因为插入元素可以在表头插,而有序链表的插入则是任意位置。
本文主要基于论文High Performance Dynamic Lock-Free Hash Tables实现。
主要问题
链表的主要操作包含insert
和remove
,先简单实现一个版本,就会看到问题所在,以下代码只用作示例:
struct node_t {
key_t key;
value_t val;
node_t *next;
};
int l_find(node_t **pred_ptr, node_t **item_ptr, node_t *head, key_t key) {
node_t *pred = head;
node_t *item = head->next;
while (item) {
int d = KEY_CMP(item->key, key);
if (d >= 0) {
*pred_ptr = pred;
*item_ptr = item;
return d == 0 ? TRUE : FALSE;
}
pred = item;
item = item->next;
}
*pred_ptr = pred;
*item_ptr = NULL;
return FALSE;
}
int l_insert(node_t *head, key_t key, value_t val) {
node_t *pred, *item, *new_item;
while (TRUE) {
if (l_find(&pred, &item, head, key)) {
return FALSE;
}
new_item = (node_t*) malloc(sizeof(node_t));
new_item->key = key;
new_item->val = val;
new_item->next = item;
// A. 如果pred本身被移除了
if (CAS(&pred->next, item, new_item)) {
return TRUE;
}
free(new_item);
}
}
int l_remove(node_t *head, key_t key) {
node_t *pred, *item;
while (TRUE) {
if (!l_find(&pred, &item, head, key)) {