[英]Lock-free queue
我也在做一個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;
}
但不確定如何繼續,使用隊列和出隊功能......
前段時間,我找到了一個很好的解決這個問題的方法。 我相信它是迄今為止發現的最小的。
該存儲庫有一個示例,說明如何使用它來創建 N 個線程(讀取器和寫入器),然后共享一個席位。
我在測試示例上做了一些基准測試並得到以下結果(以百萬次操作/秒為單位):
按緩沖區大小
按線程數
請注意線程數如何不改變吞吐量。
我認為這是解決這個問題的最終方法。 它有效並且非常快速和簡單。 即使有數百個線程和單個位置的隊列。 它可以用作線程之間的管道,在隊列內分配空間。
該存儲庫有一些用 C# 和 pascal 編寫的早期版本。 我正在努力使某些東西更加完整,以展示其真正的力量。
我希望你們中的一些人可以驗證工作或幫助提出一些想法。 或者至少,你能打破它嗎?
以及最近的 boost'con 談論這個主題: https : //github.com/boostcon/2011_presentations/raw/master/wed/lockfree_2011_slides.pdf
你可以試試這個庫,它是用 c 本機構建的。 隊列
例如
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);
(暫時離開這里,但請參閱編輯。)
你知道 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
被彈出、釋放、再次分配,並在檢查空值和交換之間再次放置,則 queue_pop 可能會失敗:
if(!tmp->next) return errno = ENODATA;
/* can fail here */
} while(!sync_swap(q->head,tmp,tmp->next));
我還不確定如何解決這個問題,但我會(希望)在我弄清楚后更新它。 暫時先不管這個。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.