kaist-cp/cs500

abortion/retry conditions for concurrent linked list

Closed this issue ยท 13 comments

In the lecture, it is explained that if compare&set is failed or if node is already marked as deleted , then insertion/deletion will be retried.

I couldn't find those conditions in the slides, if anyone wrote down or took picture of them, could you please share it?

Also, do those retries work without changing arguments of insertion/deletion?

One more question, given X->Y->Z and trying to delete Y, we need to know predecessor of Y to delete Y, so X and Y should be given as an argument, right?

  • Yes, to delete Y, it's necessary to know X as well.
  • Insertion is regarded as successful if its CAS succeeds. Deletion is regarded as successful if its first CAS succeeds. If an operation is not successful, the user of the data structure should retry with other arguments.

@jeehoonkang

Deletion is regarded as successful if its first CAS succeeds.

First CAS? I thought there is only 1 CAS. This is what I have on my notes and on the slides. You mean that delete is successful if marking is done correctly, right? But Marking is not done using a CAS operation, right? It is a fetch_or. I think fetch_add would also work too
image

Thank you!

@HaritzPuerto Thank you for pointing out my mistake. Yes, a node is regarded as deleted when the first RMW that marks the node succeeds.

@jeehoonkang

You mean checking if first RMW and CAS for deletion/insertion is enough??

When given X->Y->Z and trying to delete Y and inserting new node between Y and Z, if Y's next is marked, for insertion, next = Y.next is Z with marked 1.
If we don't check if it is marked, new node will set its next as marked Z, which makes new node already deleted as soon as it is inserted. As I remember, insertion should check if Y is marked as deleted or not, at the beginning of insertion.

For deletion, think about the situation that tries to remove Y and inserting new node next X. Even if deletion successfully marks Y's next as deleted, a node can be inserted between X and Y successfully and X's next can be changed before deletion completes. Then, second CAS of deletion, trying to set X.next = Y to X.next = Z fails, since X.next is changed to new node.

I think their success are not simply checked with only first RMW and CAS, but checking if a node is marked as deleted should be done, too.

@qkrclrl701 I couldn't understand your question... ํ˜น์‹œ ํ•œ๊ตญ์–ด๋กœ ๋จผ์ € ์–˜๊ธฐํ•  ์ˆ˜ ์žˆ์„๊นŒ์š”?

@jeehoonkang

  1. X->Y->Z, Y๋ฅผ ์ง€์šฐ๊ณ , Y์™€ Z ์‚ฌ์ด์— ์ƒˆ๋กœ์šด node๋ฅผ insertํ•˜๋Š” ๊ฒƒ์ด ๋™์‹œ์— ์ผ์–ด๋‚˜๋Š” ์ƒํ™ฉ
    deletion์—์„œ Y์˜ next๋ฅผ deleted๋กœ markํ•œ ์ดํ›„์— insertion์ด ์‹œ์ž‘๋˜๋Š” ์ƒํ™ฉ์„ ๊ฐ€์ •ํ•˜๋ฉด, new node W์˜ next๋Š” Y์˜ next๋กœ ์„ค์ •๋ ํ…๋ฐ, Y์˜ next๋Š” mark๊ฐ€ ๋œ ์ƒํ™ฉ์ด๋‹ˆ W.next = marked Z๊ฐ€ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ์ƒํ™ฉ์—์„œ insertion์˜ ๋‘๋ฒˆ์งธ CAS๋Š” ์„ฑ๊ณตํ•˜๊ณ , Y.next = W๋กœ ์„ค์ •๋˜์–ด insertion์ด ์„ฑ๊ณตํ• ํ…๋ฐ, W์˜ next๋Š” ์ฒ˜์Œ์˜ Y.next, ์ฆ‰ mark ๋œ Z๋กœ ์„ค์ •๋ ํ…Œ๋‹ˆ X->Y->W-/>Z๊ฐ€ ๋˜์–ด, ์ง€์šฐ์ง€๋„ ์•Š์€ W๋ฅผ ์ง€์› ๋‹ค๊ณ  markํ•˜๊ฒŒ ๋  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๋”ฐ๋ผ์„œ, insertion์˜ ์ฒ˜์Œ์— Y.next๊ฐ€ mark ๋˜์—ˆ๋Š”์ง€ ํ™•์ธํ•˜๊ณ , mark ๋˜์—ˆ๋‹ค๋ฉด abort ํ•ด์•ผํ•  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  1. X->Y->Z, Y๋ฅผ ์ง€์šฐ๊ณ  X์™€ Y ์‚ฌ์ด์— ์ƒˆ๋กœ์šด node๋ฅผ insert ํ•˜๋Š” ๊ฒƒ์ด ๋™์‹œ์— ์ผ์–ด๋‚˜๋Š” ์ƒํ™ฉ
    ์ฒ˜์Œ์— deletion์—์„œ Y์˜ next๋ฅผ mark ํ•˜๋Š”๊ฒƒ์ด ์„ฑ๊ณตํ•œ๋‹ค๊ณ  ํ•˜๋”๋ผ๋„, insertion์€ ์•„๋ฌด ๋ฌธ์ œ ์—†์ด ์„ฑ๊ณตํ•˜์—ฌ X->W->Y-/>Z๊ฐ€ ๋ ๊ฒƒ์ด๊ณ , deletion์˜ ๋‘๋ฒˆ์งธ CAS๋Š” X.next๋ฅผ Y์—์„œ Z๋กœ ๋ฐ”๊พธ๋ ค๊ณ  ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ๋ฐ, X.next๊ฐ€ ์ด๋ฏธ W๋กœ ๋ฐ”๋€Œ์—ˆ์œผ๋‹ˆ CAS๊ฐ€ ์‹คํŒจํ•˜๊ณ  deletion์ด ์‹คํŒจํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‹ต๋ณ€์ฃผ์‹  ๋‚ด์šฉ์—์„œ๋Š” deletion์˜ ์ฒซ RMW๊ฐ€ ์„ฑ๊ณตํ•˜๋ฉด deletion์ด ์„ฑ๊ณตํ•œ ๊ฒƒ์ด๋ผ๊ณ  ํ•˜์…จ๋Š”๋ฐ, ์ฒซ RMW๊ฐ€ ์„ฑ๊ณตํ•˜๋”๋ผ๋„ deletion์ด ์‹คํŒจํ•˜๋Š” ์ƒํ™ฉ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๋‹จ์ˆœํžˆ RMW, CAS์˜ ์„ฑ๊ณต ์—ฌ๋ถ€๋งŒ์ด ์•„๋‹ˆ๋ผ, next๊ฐ€ mark ๋˜์—ˆ๋Š”์ง€ ๋˜ํ•œ ํ™•์ธํ•ด์•ผ ํ•  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

  • Insertion์€ CAS๋ฅผ ํ•œ๋ฒˆ๋งŒ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • ๋ง์”€ํ•˜์‹ ๋Œ€๋กœ Insertion์€ Y.next๊ฐ€ mark๋˜์—ˆ๋‹ค๋ฉด abortํ•ฉ๋‹ˆ๋‹ค.
  • Deletion์—์„œ markingํ•˜๋Š” RMW๊ฐ€ ์„ฑ๊ณตํ•˜๋ฉด deletion ์ž์ฒด๊ฐ€ ์„ฑ๊ณตํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ฆฌ์ŠคํŠธ์— ๋ฌผ๋ฆฌ์ ์œผ๋กœ Y๊ฐ€ ๋‚จ์•„์žˆ๋”๋ผ๋„, ๋…ผ๋ฆฌ์ ์œผ๋กœ๋Š” ์—†๋Š” ๊ฒƒ์œผ๋กœ ์ทจ๊ธ‰๋ฉ๋‹ˆ๋‹ค.

@jeehoonkang

๋ช…์พŒํ•œ ๋‹ต๋ณ€ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด, iterate ํ•  ๋•Œ delete๋œ node๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ ์žˆ๋Š” ๊ฒฝ์šฐ๋„ ์กด์žฌํ•  ๊ฒƒ ๊ฐ™์€๋ฐ์š”,
V->W-/>X-/>Y->Z

์ด๋Ÿฌํ•œ ๊ฒฝ์šฐ์—๋Š” V ์ดํ›„์— ๋ฐ”๋กœ Y๋กœ ์ด๋™ํ•ด์•ผ ํ• ํ…๋ฐ, ์ˆ˜์—…์‹œ๊ฐ„์— ๋ง์”€ํ•˜์‹ ๋Œ€๋กœ W์˜ next๊ฐ€ mark๋œ์ง€ ํ™•์ธํ•œ ๋’ค์— mark๋˜์—ˆ์œผ๋ฉด W.next๋กœ ์ด๋™ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ while loop๋กœ next๊ฐ€ mark ๋˜์ง€ ์•Š์€ ์ฒซ๋ฒˆ์งธ node๋ฅผ ์ฐพ์•„ ๊ทธ node๋กœ ์ด๋™ํ•ด์•ผ ํ•  ๊ฒƒ ๊ฐ™์€๋ฐ ๋งž๋‚˜์š”?

I think two deletion case is not handled in our algorithm. There was a question about it some days ago but it was buried.
See the concurrent deletion section on link below.
https://en.m.wikipedia.org/wiki/Non-blocking_linked_list

@qkrclrl701 Yes, during iteration, a thread should (1) skip the marked-as-deleted node, or (2) try to remove the marked-as-deleted node and proceed.

@CauchyComplete

I think two deletion case is not handled in our algorithm.

May I ask if you can elaborate on it?

@CauchyComplete

I think two deletion case is not handled in our algorithm.

May I ask if you can elaborate on it?

Hello @jeehoonkang ,
here #63 (comment)

Yeah I was referring that issue. And think it is not that simple to handle