此外,我正在执行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;
}
但不确定如何继续,有队列和出队功能......
答案 0 :(得分:2)
您的伪代码可能(并且很可能确实)受到ABA problem的影响,因为只检查了指针,而不是附带的唯一标记,您会发现this paper的使用考虑并作为无锁队列实施的一般指南及其缺陷。
在处理无锁编程时,阅读Herb Sutter的作品也是一个好主意,因为他对所要求的内容,为什么需要以及潜在的弱点提供了很好的,有见地的解释(尽管他们有些年长发现包含一些隐藏/未发现问题的出版物/文章)。
答案 1 :(得分:2)
以及最近的boost'con谈论这个主题: https://github.com/boostcon/2011_presentations/raw/master/wed/lockfree_2011_slides.pdf
答案 2 :(得分:2)
有时候,我发现了a nice solution这个问题。我相信它是迄今为止发现的最小的。
该存储库提供了一个示例,说明如何使用该存储库创建N个线程(读者和作家),然后使他们共享一个席位。
我在测试示例中建立了一些基准,并获得了以下结果(以百万次操作/秒为单位):
按缓冲区大小
按线程数
注意线程数如何不改变吞吐量。
我认为这是解决此问题的最终方法。它的工作原理是令人难以置信的快速和简单。即使有数百个线程和一个位置的队列。它可以用作线程之间的管道,在队列内分配空间。
该存储库具有一些用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);