无锁队列

时间:2011-05-22 15:48:52

标签: c queue lock-free

enter image description here enter image description here

此外,我正在执行c实现,目前具有队列结构:

typedef struct queueelem {
    queuedata_t data;
    struct queueelem *next;
} queueelem_t;

typedef struct queue {
    int capacity;
    int size;
    queueelem_t *head;
    queueelem_t *tail;
} queue_t;

queue_t *
queue_init(int capacity)
{
    queue_t *q = (queue_t *) malloc(sizeof(queue_t));
    q->head = q->tail = NULL;
    q->size = 0;
    q->capacity = capacity;
    return q;
}

int CompareAndExchange (void **a, void *comparand,void *new) {
    int success = 0;
    pthread_mutex_lock(&CE_MUTEX);
    if ((*a) != comparand) {
       (*a) = new;
       //return     TRUE
       success = 1;
    }
    pthread_mutex_unlock(&CE_MUTEX);     
   //return     FALSE
    return success;
 }

但不确定如何继续,有队列和出队功能......

  • 代码怎么样?

5 个答案:

答案 0 :(得分:2)

您的伪代码可能(并且很可能确实)受到ABA problem的影响,因为只检查了指针,而不是附带的唯一标记,您会发现this paper的使用考虑并作为无锁队列实施的一般指南及其缺陷。

在处理无锁编程时,阅读Herb Sutter的作品也是一个好主意,因为他对所要求的内容,为什么需要以及潜在的弱点提供了很好的,有见地的解释(尽管他们有些年长发现包含一些隐藏/未发现问题的出版物/文章)。

答案 1 :(得分:2)

答案 2 :(得分:2)

有时候,我发现了a nice solution这个问题。我相信它是迄今为止发现的最小的。

该存储库提供了一个示例,说明如何使用该存储库创建N个线程(读者和作家),然后使他们共享一个席位。

我在测试示例中建立了一些基准,并获得了以下结果(以百万次操作/秒为单位):

按缓冲区大小

throughput

按线程数

enter image description here

注意线程数如何不改变吞吐量。

我认为这是解决此问题的最终方法。它的工作原理是令人难以置信的快速和简单。即使有数百个线程和一个位置的队列。它可以用作线程之间的管道,在队列内分配空间。

该存储库具有一些用C#和pascal编写的早期版本。我正在努力使某些东西更完整地抛光,以显示其真正的力量。

我希望你们中的一些人可以验证工作或提供一些想法。或者至少可以打破它?

答案 3 :(得分:0)

(暂时离开这里,但请看编辑。)

  

你知道C中无锁队列的实现吗?

我最近写了无锁队列(http://www.ideone.com/l2QRp)。我实际上无法保证它正常工作,但是我无法找到任何错误,我已经在几个单线程程序中使用它而没有任何问题,所以它没有太明显的错误

琐碎的用法示例:

queue_t queue;
int val = 42;
queue_init(&queue,sizeof val);
queue_put(&queue,&val);
val = 0; 
queue_pop(&queue,&val);
printf("%i\n",val); // 42
queue_destroy(&queue);

编辑:

正如@Alexey Kukanov指出的那样,如果tmp被弹出,释放,再次分配,并且在检查null和交换之间再次放置,则queue_pop可能会失败:

    if(!tmp->next) return errno = ENODATA;
    /* can fail here */
    } while(!sync_swap(q->head,tmp,tmp->next));

我还不确定如何解决这个问题,但是一旦我搞清楚,我(希望)会更新这个。现在,无视这一点。

答案 4 :(得分:0)

您可以尝试使用c native构建的该库。 lfqueue

例如

int* int_data;
lfqueue_t my_queue;

if (lfqueue_init(&my_queue) == -1)
    return -1;

/** Wrap This scope in other threads **/
int_data = (int*) malloc(sizeof(int));
assert(int_data != NULL);
*int_data = i++;
/*Enqueue*/
 while (lfqueue_enq(&my_queue, int_data) == -1) {
    printf("ENQ Full ?\n");
}

/** Wrap This scope in other threads **/
/*Dequeue*/
while  ( (int_data = lfqueue_deq(&my_queue)) == NULL) {
    printf("DEQ EMPTY ..\n");
}

// printf("%d\n", *(int*) int_data );
free(int_data);
/** End **/

lfqueue_destroy(&my_queue);