[Concurrency] Test And Set (TAS)

Test And Set(์ดํ•˜ TAS)๋Š” ๋™์‹œ์„ฑ ํ™˜๊ฒฝ์—์„œ์˜ ๋™๊ธฐํ™”๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•œ ๊ธฐ๋ฒ• ์ค‘ ํ•˜๋‚˜๋‹ค.

Compare And Swap์ด Lock-free๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•œ ์—ฐ์‚ฐ ๋‹จ์œ„๋กœ ์‘์šฉ๋œ๋‹ค๋ฉด, TAS๋Š” Spin-Lock์„ ๊ตฌํ˜„ํ•˜๋Š”๋ฐ ์ฃผ๋กœ ์‚ฌ์šฉ๋œ๋‹ค. Mutex ๊ฐ™์€ lock ๊ธฐ๋ฐ˜์˜ ๋™๊ธฐํ™” ๋งค์ปค๋‹ˆ์ฆ˜์€ ๋ณดํ†ต ์ด๋Ÿฐ๊ฑธ ํ†ตํ•ด ๊ตฌํ˜„๋œ๋‹ค๊ณ  ๋ณด๋ฉด ๋œ๋‹ค.

์•„๋ž˜๋Š” TAS์˜ ์›๋ฆฌ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” C ์ฝ”๋“œ๋‹ค.

// lock์„ ํš๋“ํ•˜์ง€ ๋ชปํ–ˆ์œผ๋ฉด true ๋ฐ˜ํ™˜
// lock์„ ํš๋“ํ–ˆ๋‹ค๋ฉด true๋กœ ์„ค์ •ํ•˜๊ณ  false ๋ฐ˜ํ™˜
bool test_and_set(bool* locked) {
    if(*locked) {
        return true;
    } else {
        *locked = true;
        return false;
    }
}

์ด๋ฏธ lock์„ ์ ์œ ํ•˜๊ณ  ์žˆ๋‹ค๋ฉด true๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ , ์•„๋‹ˆ๋ผ๋ฉด false๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

์ด๊ฑธ ์‘์šฉํ•˜๋ฉด ๋ฐ”๋กœ Spin-Lock์„ ํ†ตํ•ด ๋™๊ธฐํ™”๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
์•„๋ž˜๋Š” ๋ฐฉ๊ธˆ ์ž‘์„ฑํ•œ test_and_set์„ ์ด์šฉํ•œ spin-lock์˜ ๊ตฌํ˜„๋ก€๋‹ค.

... 
bool lock = false; // lock์šฉ ๊ณต์œ ๋ณ€์ˆ˜
...

// A thread
void spawn_thread(bool* lock) {
    // lock์„ ์ ์œ ํ•  ๋•Œ๊นŒ์ง€ ๋ฌดํ•œ๋ฃจํ”„๋กœ ๋Œ€๊ธฐ (Spin-Lock)
    while(!test_and_set(lock));

    // ์ ์œ ํ–ˆ์„ ๊ฒฝ์šฐ ์ง„์ž…
    ...์ž‘์—…

    // lock ํ•ด์ œ
    *lock = false;
}

๋‹ค๋งŒ ์ด ์ฝ”๋“œ๋Š” ๊ฐœ๋…์„ ๋ณด์—ฌ์ฃผ๊ธฐ ์œ„ํ•ด ์ž‘์„ฑํ•œ ๊ฒƒ์ด๋ผ ์‹ค์ œ๋กœ atomicํ•˜๊ฒŒ ๋™์ž‘ํ•˜์ง€๋Š” ์•Š๋Š”๋‹ค.

๋Œ€์‹  gcc๋‚˜ clang์—์„œ๋Š” atomicํ•œ TAS ํ•จ์ˆ˜๋กœ __sync_lock_test_and_set์ด๋ผ๋Š” ํ•จ์ˆ˜๋ฅผ ์ œ๊ณตํ•œ๋‹ค.
์ €๋Ÿฐ๊ฑธ ์“ฐ๋ฉด ๋œ๋‹ค.




์–ด์…ˆ๋ธ”๋ฆฌ ์ˆ˜์ค€ (x86-64)

C์—์„œ ํŠน์ˆ˜ํ•œ ํ•จ์ˆ˜์˜ ํ˜•ํƒœ๋กœ๋งŒ ๊ตฌํ˜„์ด ๊ฐ€๋Šฅํ•œ ๊ฒƒ์„ ๋ณด๋ฉด ์•Œ๊ฒ ์ง€๋งŒ, ์ด๊ฑด CPU์˜ ๋ช…๋ น์— ์˜์กด์ ์ธ ๊ธฐ๋Šฅ์ด๋‹ค.
x86 ํ”„๋กœ์„ธ์„œ์—์„œ TAS๋Š” "xchgb"์™€ ๊ฐ™์€ ๋ช…๋ น์„ ํ†ตํ•ด ์ œ๊ณต๋œ๋‹ค.

movb $1, %al
xchgb %al, (%rdi) ; TAS
...



ํšจ์œจ์„ฑ?

์‚ฌ์‹ค TAS ๊ธฐ๋ฐ˜์˜ ์Šคํ•€๋ฝ์€ ํšจ์œจ์„ฑ์ด ๋”ฑํžˆ ์ข‹์€ํŽธ์ด ์•„๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์ธ ์†Œํ”„ํŠธ์›จ์–ด ์ˆ˜์ค€์—์„œ๋Š” Mutex ๊ฐ™์€ ๊ธฐ๋ณธ ๋ฝ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ํ›จ์”ฌ ๋А๋ฆฌ๊ณ  ๋น„ํšจ์œจ์ ์ด๋‹ค.
์Šคํ•€๋ฝ์ด ์ข‹์€ ์„ฑ๋Šฅ์„ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ์€ ๋งค์šฐ ๊ทน๋‹จ์ ์ธ ์ƒํ™ฉ ๋ฟ์ด๋‹ˆ, ์ผ๋ฐ˜์ ์œผ๋กœ๋Š” ์“ฐ์ง€ ์•Š๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•œ๋‹ค.

์Šค๋ ˆ๋“œ์˜ ์ˆ˜๊ฐ€ ๋ฌผ๋ฆฌ ์ฝ”์–ด์˜ ์ˆ˜๋ฅผ ๋„˜์ง€ ์•Š๊ณ , ํ• ๋‹น์ด ๋งŽ์ง€ ์•Š์„ ๊ฒฝ์šฐ์—๋Š” ์Šคํ•€๋ฝ์ด ์ข‹์„ ์ˆ˜ ์žˆ๋‹ค๊ณ  ํ•œ๋‹ค.



์ฐธ์กฐ
https://en.wikipedia.org/wiki/Test-and-set
https://stackoverflow.com/questions/3659336/compare-and-swap-vs-test-and-set
https://mmomtchev.medium.com/spinlock-vs-mutex-performance-3f73de53a460