contributed by < jeffrey.w
>
本文將參考 Michael & Scott algorithm
,以 C11 規格
[1
] 實作 non-blocking concurrent queue
。
由於 Michael & Scott algorithm
是使用 singly-linked list
實作 non-blocking concurrent queue
,所以本文會先實驗如何實作一個 non-blocking singly-linked list
,重點會放在 concurrent insertion。
關於 concurrent linked list
,2001 年 Harris
提出一個 non-blocking
的 solution
[2
],這個 solution
使用了 compare-and-swap
來完成。
Harris's solution
對於 non-blocking singly-linked list
的 insertion
是這樣 [2
]:
Insert node n aftre node *p
用 C11 規格
實作 Harris's solution
[harris_solution.c
]
有一行要特別挑出來實驗一下
這樣寫對嗎?我們看一下 C11 規格
§7.17.7.4/1
_Bool atomic_compare_exchange_strong(volatile A *object, C *expected, C desired);
§7.17.7.4/3
能不能把 atomic_compare_exchange_strong(&p->next, &next, &new)
改成這樣?
以下圖為例來檢視 (p->next, next, new)
和 (&p->next, &next, &new)
的差別
_Bool atomic_compare_exchange_strong(volatile A *object, C *expected, C desired);
object
和 expected
都是 pointer,如果這兩個 pointer 所指向的 location 的前 n 個 bytes 一樣的話 (n == sizeof(*object)),desired
的值就會被 copy 到 object
所指向的 location。
所以,如果改成 atomic_compare_exchange_strong(p->next, next, new)
,由於 object
這個 pointer (p->next
) 指向 NULL,所以會發生 Segmentation fault
。
用兩條 thread
實驗一下 Harris’s solution
的實作
上面這個實作純粹是在實驗 insert element in concurrency,所以每次的 insert 都 insert 到 list 的前面,並不是 insert 到 list 的最後面。
至於驗證 insert 正不正確是看最後的結果 list 的個數正不正確。
calc_length
是參考 ConcurrentLinkedQueue::size()
的寫法,計算長度的過程中如果發生 element
的 remove
或 insert
,計算的結果就會不正確。
[list.c
]
上面的實作是 insert 到 list 的前面,而不是 tail,所以這裡實作一個 insertion 是 insert 到 list
的 tail
。
在這個實作會增加兩個 pointer
: head
和 tail
,在下圖這個例子,list
有兩個 elements。是 2 個 elements,不是 3 個,因為藍底白字那個 node 是 dummy,就是 head
指向的 struct node_t。
所以一個空白的 list
會是這樣
參考 Michael & Scott algorithm
對 enque
的 pseudo-code
,在 insert node 之後,再用 atomic instruction CAS 將 tail 指到最後一個 node。
修改過的 insert 像這樣
[list.c
]
跟 Harris's solution
不一樣的是這一行 atomic_compare_exchange_strong(&list->tail, &tail, &new);
,這裡參考 Michael & Scott algorithm
enque
的 pseudo-code
[3
],使用 CAS 將 list->tail
指向新增的 node (下圖的 E17)。
參考 jserv 老師的 concurrent-ll
,寫一段 code 來檢驗 performance。
concurrency
non-blocking
blocking
concurrent queue
linked list
Harris's solution
algorithm