๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด/C++ ๊ธฐ์ดˆ

[C++] 21. ์Šค๋ ˆ๋“œ ๊ฒฝ์Ÿ ์ƒํƒœ(Race condition), ๋ฎคํ…์Šค(mutex), ๋ฐ๋“œ๋ฝ, std::conditional_variable, std::async

by ์„œ์•„๋ž‘๐Ÿ˜ 2023. 8. 22.

 

 

์ง€๋‚œ ํฌ์ŠคํŒ…์—์„œ๋Š” ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ์™€ ๋ฉ€ํ‹ฐ ํ”„๋กœ์„ธ์Šค, std::thread์— ๋Œ€ํ•ด ์‚ดํŽด๋ดค์Šต๋‹ˆ๋‹ค. [C++] 20. ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ(Multi-Threads)

์˜ค๋Š˜์€ ์ด์–ด์„œ ์Šค๋ ˆ๋“œ๋ผ๋ฆฌ์˜ ์ถฉ๋Œ ๋ฌธ์ œ์™€ lock ๋ฌธ์ œ๋ฅผ ์‚ดํŽด๋ณด๊ณ , ์Šค๋ ˆ๋“œ๋“ค(workers)์ด wait์ƒํƒœ์—์„œ ๋Œ€๊ธฐํ•˜๋‹ค๊ฐ€ ์ž‘์—…์ด ์žˆ์„ ๋•Œ ์•Œ์•„์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ์Šค๋งˆํŠธํ•œ ์šด์˜๋ฐฉ์‹์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ณ ์ž ํ•ฉ๋‹ˆ๋‹ค.

 

 

 

๊ณต์œ ์ž์›(Shared Resources)๊ณผ ์ž„๊ณ„์˜์—ญ(Critical Section)

์Šค๋ ˆ๋“œ(Thread)๋Š” ํ”„๋กœ์„ธ์Šค ๋‚ด์—์„œ ์‹คํ–‰๋˜๋Š” ์ž‘์€ ์‹คํ–‰ ๋‹จ์œ„๋กœ, ํ•˜๋‚˜์˜ ํ”„๋กœ์„ธ์Šค ์•ˆ์— ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ์กด์žฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋•Œ ์Šค๋ ˆ๋“œ ๊ฐ„์—๋Š” ๊ณต์œ ์ž์›(Shared Resource)๊ณผ ๊ด€๋ จ๋œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๊ณต์œ ์ž์›์„ ์•ˆ์ „ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์ž„๊ณ„์˜์—ญ(Critical Section)์ด๋ผ๋Š” ๊ฐœ๋…์ด ๋“ฑ์žฅํ•ฉ๋‹ˆ๋‹ค.

๊ณต์œ ์ž์›์€ ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— ์ ‘๊ทผํ•˜๊ฑฐ๋‚˜ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋‚˜ ์ž์›์„ ๋งํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฉ”๋ชจ๋ฆฌ ๊ณต๊ฐ„, ํŒŒ์ผ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ๋“ฑ์ด ๊ณต์œ ์ž์›์— ํ•ด๋‹นํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์Šค๋ ˆ๋“œ๋“ค์€ ์ด๋Ÿฌํ•œ ๊ณต์œ ์ž์›์— ์ ‘๊ทผํ•˜๊ฑฐ๋‚˜ ์ˆ˜์ •ํ•˜๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— ๊ณต์œ ์ž์›์„ ์ ‘๊ทผํ•˜๊ฑฐ๋‚˜ ์ˆ˜์ •ํ•˜๋ ค๊ณ  ํ•  ๋•Œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋•Œ ์ž„๊ณ„์˜์—ญ์ด๋ž€, ๊ณต์œ ์ž์›์— ๋Œ€ํ•œ ์ ‘๊ทผ์„ ๋™๊ธฐํ™”ํ•˜์—ฌ ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๋งŒ์ด ์ž„๊ณ„์˜์—ญ์— ์ง„์ž…ํ•˜์—ฌ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋„๋ก ํ•˜๋Š” ๋ถ€๋ถ„์„ ๋งํ•ฉ๋‹ˆ๋‹ค. ์ด๋Š” ๋‹ค์ˆ˜์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ๊ณต์œ ์ž์›์„ ์•ˆ์ „ํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ๋ฉ”์ปค๋‹ˆ์ฆ˜์ž…๋‹ˆ๋‹ค.

์ž„๊ณ„์˜์—ญ์„ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ๊ธฐ๋ฒ•์—๋Š” ๋ฎคํ…์Šค(Mutex), ์„ธ๋งˆํฌ์–ด(Semaphore), ์Šค๋ ˆ๋“œ-๋กœ์ปฌ ์ €์žฅ์†Œ(Thread-Local Storage) ๋“ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋™๊ธฐํ™” ๊ธฐ๋ฒ•์„ ์‚ฌ์šฉํ•˜์—ฌ ์Šค๋ ˆ๋“œ๋“ค์ด ์ž„๊ณ„์˜์—ญ์— ์ ‘๊ทผํ•  ๋•Œ ์„œ๋กœ์˜ ์ž‘์—…์ด ๊ฒน์น˜์ง€ ์•Š๋„๋ก ๋ณด์žฅํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋กœ์จ ๋ฐ์ดํ„ฐ ์ผ๊ด€์„ฑ๊ณผ ์•ˆ์ •์„ฑ์„ ์œ ์ง€ํ•˜๋ฉด์„œ ๊ณต์œ ์ž์›์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์š”์•ฝํ•˜์ž๋ฉด, ์Šค๋ ˆ๋“œ ๊ฐ„์— ๊ณต์œ ํ•˜๋Š” ์ž์›์— ์ ‘๊ทผํ•  ๋•Œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ์ž„๊ณ„์˜์—ญ์ด๋ผ๋Š” ๊ฐœ๋…์ด ๋“ฑ์žฅํ•ฉ๋‹ˆ๋‹ค. ์ž„๊ณ„์˜์—ญ์€ ๋™๊ธฐํ™” ๊ธฐ๋ฒ•์„ ํ†ตํ•ด ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ์•ˆ์ „ํ•˜๊ฒŒ ๊ณต์œ ์ž์›์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.

 

 

 

๊ฒฝ์Ÿ์ƒํƒœ(Race Condition)

์Šค๋ ˆ๋“œ์˜ ๊ฒฝ์Ÿ์ƒํƒœ(Race Condition)๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ๊ณต์œ ์ž์›์— ์ ‘๊ทผํ•˜๊ฑฐ๋‚˜ ์ˆ˜์ •ํ•˜๋ ค๊ณ  ํ•  ๋•Œ, ์Šค๋ ˆ๋“œ๋“ค์˜ ์‹คํ–‰ ์ˆœ์„œ์— ์˜์กดํ•˜์—ฌ ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๊ฒฐ๊ณผ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ์ƒํ™ฉ์„ ๋งํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ƒํ™ฉ์€ ์Šค๋ ˆ๋“œ ๊ฐ„์˜ ๊ฒฝ์Ÿ์œผ๋กœ ์ธํ•ด ๋ฐœ์ƒํ•˜๋ฉฐ, ํ”„๋กœ๊ทธ๋žจ์˜ ์‹คํ–‰ ๊ฒฐ๊ณผ๊ฐ€ ์ผ๊ด€๋˜์ง€ ์•Š๊ฑฐ๋‚˜ ์ž˜๋ชป๋œ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฒฝ์Ÿ์ƒํƒœ๋Š” ์ฃผ๋กœ ๊ณต์œ ์ž์›์— ๋Œ€ํ•œ ์ ‘๊ทผ์ด๋‚˜ ์ˆ˜์ •์ด ๋™๊ธฐํ™” ์—†์ด ์ด๋ฃจ์–ด์ง€๋Š” ๊ฒฝ์šฐ์— ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— ๊ฐ™์€ ๋ณ€์ˆ˜๋ฅผ ์ฝ๊ฑฐ๋‚˜ ์ˆ˜์ •ํ•˜๋ ค๊ณ  ํ•  ๋•Œ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์ด๋Ÿฌํ•œ ์ž‘์—…์ด ์ž˜๋ชป๋œ ์ˆœ์„œ๋กœ ์ด๋ฃจ์–ด์ง€๋ฉด, ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๊ฐ’์ด๋‚˜ ์˜ค์ž‘๋™์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฒฝ์Ÿ์ƒํƒœ๋Š” ๋‹ค์–‘ํ•œ ๋ฌธ์ œ๋ฅผ ์•ผ๊ธฐํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ๊ทธ ์ค‘ ์ผ๋ฐ˜์ ์ธ ๋ฌธ์ œ๋“ค์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

1. ๋ฐ์ดํ„ฐ ์ผ๊ด€์„ฑ ๋ฌธ์ œ: ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— ๊ฐ™์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๊ฒฝ์šฐ, ์Šค๋ ˆ๋“œ ๊ฐ„์— ๋ฐ์ดํ„ฐ๊ฐ€ ์ผ๊ด€์„ฑ ์—†์ด ๋ณ€๊ฒฝ๋˜์–ด ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๊ฒฐ๊ณผ๋ฅผ ์ดˆ๋ž˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2. ๊ต์ฐฉ์ƒํƒœ(Deadlock): ๋‘ ๊ฐœ ์ด์ƒ์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ์„œ๋กœ ์ƒ๋Œ€๋ฐฉ์ด ์ ‘๊ทผํ•˜๊ณ  ์žˆ๋Š” ์ž์›์„ ๊ธฐ๋‹ค๋ฆฌ๋ฉฐ ๋ฌดํ•œํžˆ ๋Œ€๊ธฐํ•˜๋Š” ์ƒํƒœ๋กœ, ํ”„๋กœ๊ทธ๋žจ์ด ๋ฉˆ์ถ”๋Š” ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

3. ์“ฐ๊ธฐ ํ›„ ์ฝ๊ธฐ ๋ฌธ์ œ: ํ•œ ์Šค๋ ˆ๋“œ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๋„์ค‘์— ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๊ฐ€ ๊ฐ™์€ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์œผ๋ฉด, ๋ฐ์ดํ„ฐ์˜ ์ผ๊ด€์„ฑ์ด ๊นจ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

4. ์ธํ„ฐ๋ŸฝํŠธ ๋ฌธ์ œ: ์ธํ„ฐ๋ŸฝํŠธ๋‚˜ ํƒ€์ด๋จธ ๋“ฑ์˜ ์™ธ๋ถ€ ์š”์ธ์œผ๋กœ ์ธํ•ด ์Šค๋ ˆ๋“œ์˜ ์‹คํ–‰์ด ์ค‘๋‹จ๋  ๋•Œ, ๊ณต์œ ์ž์›์˜ ์ƒํƒœ๊ฐ€ ์ผ๊ด€๋˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์Šค๋ ˆ๋“œ ๊ฐ„์˜ ๋™๊ธฐํ™” ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์‚ฌ์šฉํ•˜์—ฌ ๊ฒฝ์Ÿ์ƒํƒœ๋ฅผ ๋ฐฉ์ง€ํ•˜๊ฑฐ๋‚˜ ์ œ์–ดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ฎคํ…์Šค(Mutex), ์„ธ๋งˆํฌ์–ด(Semaphore), ์ž„๊ณ„์˜์—ญ(Critical Section) ๋“ฑ์˜ ๊ธฐ๋ฒ•์„ ํ™œ์šฉํ•˜์—ฌ ๊ณต์œ ์ž์›์˜ ์ ‘๊ทผ์„ ์กฐ์ ˆํ•จ์œผ๋กœ์จ ๊ฒฝ์Ÿ์ƒํƒœ๋ฅผ ํ”ผํ•˜๊ณ  ํ”„๋กœ๊ทธ๋žจ์˜ ์•ˆ์ •์„ฑ์„ ํ™•๋ณดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

 

๋ฐ๋“œ๋ฝ(Dead Lock)

๋ฐ๋“œ๋ฝ(Deadlock)์€ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๋™๊ธฐํ™” ๋ฌธ์ œ ์ค‘ ํ•˜๋‚˜๋กœ, ๋‘ ๊ฐœ ์ด์ƒ์˜ ์Šค๋ ˆ๋“œ๋‚˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์„œ๋กœ๊ฐ€ ๊ฐ€์ง„ ์ž์›์„ ์ ์œ ํ•˜๊ณ  ์žˆ์–ด์„œ ๊ณ„์†ํ•ด์„œ ์ƒ๋Œ€๋ฐฉ์ด ์ ์œ ํ•˜๊ณ  ์žˆ๋Š” ์ž์›์„ ๊ธฐ๋‹ค๋ฆฌ๋ฉฐ ์•„๋ฌด ๋™์ž‘๋„ ์ˆ˜ํ–‰ํ•˜์ง€ ๋ชปํ•˜๋Š” ์ƒํƒœ๋ฅผ ๋งํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์ƒํ™ฉ์—์„œ๋Š” ๊ฐ ์Šค๋ ˆ๋“œ๋‚˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋‹ค์Œ ๋‹จ๊ณ„๋กœ ์ง„ํ–‰ํ•˜์ง€ ๋ชปํ•˜๋ฏ€๋กœ, ํ”„๋กœ๊ทธ๋žจ์ด ๋ฌดํ•œํžˆ ๋ฉˆ์ถ˜ ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ฐ๋“œ๋ฝ์ด ๋ฐœ์ƒํ•˜๋ ค๋ฉด ์•„๋ž˜์˜ ๋„ค ๊ฐ€์ง€ ์กฐ๊ฑด์ด ๋ชจ๋‘ ์ถฉ์กฑ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

1. ์ƒํ˜ธ ๋ฐฐ์ œ(Mutual Exclusion): ์ž์›์€ ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๋‚˜ ํ”„๋กœ์„ธ์Šค๋งŒ์ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ํ•œ ์ž์›์€ ๋™์‹œ์— ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๋‚˜ ํ”„๋กœ์„ธ์Šค์— ์˜ํ•ด ์‚ฌ์šฉ๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

2. ์ ์œ ์™€ ๋Œ€๊ธฐ(Hold and Wait): ์ตœ์†Œํ•œ ํ•˜๋‚˜์˜ ์ž์›์„ ์ ์œ ํ•œ ์ƒํƒœ์—์„œ ๋‹ค๋ฅธ ์ž์›์„ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์Šค๋ ˆ๋“œ๋‚˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

3. ๋น„์„ ์ (No Preemption): ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๋‚˜ ํ”„๋กœ์„ธ์Šค์— ์˜ํ•ด ์ ์œ ๋œ ์ž์›์„ ๊ฐ•์ œ๋กœ ๋นผ์•—์„ ์ˆ˜ ์—†์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ž์›์€ ํ•ด๋‹น ์Šค๋ ˆ๋“œ๋‚˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋ฐ˜๋‚ฉํ•˜๊ธฐ ์ „๊นŒ์ง€ ์ ์œ ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

4. ์ˆœํ™˜ ๋Œ€๊ธฐ(Circular Wait): ๊ฐ ์Šค๋ ˆ๋“œ๋‚˜ ํ”„๋กœ์„ธ์Šค๋Š” ๋‹ค์Œ ์Šค๋ ˆ๋“œ๋‚˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ ์œ ํ•œ ์ž์›์„ ๊ธฐ๋‹ค๋ฆฌ๋ฉฐ ์›ํ˜•์œผ๋กœ ๋Œ€๊ธฐํ•˜๋Š” ์ƒํ™ฉ์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

#include <iostream>
#include <thread>
#include <mutex>

std::mutex mtx1;
std::mutex mtx2;

void threadFunction1() {
    std::lock_guard<std::mutex> lock1(mtx1);
    std::this_thread::sleep_for(std::chrono::milliseconds(100)); // ์ž ์‹œ ๋Œ€๊ธฐ
    std::cout << "Thread 1 locked mtx1" << std::endl;
    std::this_thread::sleep_for(std::chrono::milliseconds(100)); // ์ž ์‹œ ๋Œ€๊ธฐ

    std::lock_guard<std::mutex> lock2(mtx2);
    std::cout << "Thread 1 locked mtx2" << std::endl;
}

void threadFunction2() {
    std::lock_guard<std::mutex> lock2(mtx2);
    std::this_thread::sleep_for(std::chrono::milliseconds(100)); // ์ž ์‹œ ๋Œ€๊ธฐ
    std::cout << "Thread 2 locked mtx2" << std::endl;
    std::this_thread::sleep_for(std::chrono::milliseconds(100)); // ์ž ์‹œ ๋Œ€๊ธฐ

    std::lock_guard<std::mutex> lock1(mtx1);
    std::cout << "Thread 2 locked mtx1" << std::endl;
}

int main() {
    std::thread t1(threadFunction1);
    std::thread t2(threadFunction2);

    t1.join();
    t2.join();

    return 0;
}

 

์œ„ ์˜ˆ์ œ์—์„œ๋Š” ๋‘ ๊ฐœ์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ๊ฐ์ž ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•˜๋ฉด์„œ ๋‘ ๊ฐœ์˜ ๋ฎคํ…์Šค(mtx1, mtx2)๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. Function1์—์„œ๋Š” mtx1์„ ์ ์œ ํ•œ ์ฑ„๋กœ mtx2๋ฅผ ์ ์œ ํ•˜๋ ค๊ณ  ํ•˜๊ณ , Function2์—์„œ๋Š” mtx2๋ฅผ ์ ์œ ํ•œ ์ฑ„๋กœ mtx1์„ ์ ์œ ํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ๋ฐ๋“œ๋ฝ์ด ๊ฑธ๋ฆฐ ์ƒํ™ฉ์ž…๋‹ˆ๋‹ค. 

์‹ค์ œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ๋Š” ์ด๋Ÿฌํ•œ ๋ฐ๋“œ๋ฝ ์ƒํ™ฉ์„ ํ”ผํ•˜๊ณ ์ž ๋ฎคํ…์Šค๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์‚ฌ์šฉํ•˜๊ณ , ์ˆœ์„œ๋Œ€๋กœ ์ ์œ ํ•˜๊ฑฐ๋‚˜ ํš๋“ํ•˜๋Š” ๋“ฑ์˜ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ๋“œ๋ฝ์„ ์˜ˆ๋ฐฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

 

 

๋ฎคํ…์Šค(Mutex)

๋ฎคํ…์Šค(Mutex)๋Š” ์ƒํ˜ธ ๋ฐฐ์ œ(Mutual Exclusion)๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•œ ๋™๊ธฐํ™” ๊ธฐ๋ฒ• ์ค‘ ํ•˜๋‚˜๋กœ, ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์Šค๋ ˆ๋“œ๋‚˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๊ณต์œ  ์ž์›์— ๋™์‹œ์— ์ ‘๊ทผํ•˜๋Š” ๊ฒƒ์„ ๋ง‰๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ๋ฎคํ…์Šค๋Š” ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๋งŒ์ด ํŠน์ • ์ž์›์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์ œ์–ดํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

๋ฎคํ…์Šค๋Š” ํฌ๊ฒŒ ๋‘ ๊ฐ€์ง€ ์ƒํƒœ๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค.

1. ์ž ๊ธˆ(Locked) ์ƒํƒœ: ๋ฎคํ…์Šค๊ฐ€ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ์— ์˜ํ•ด ์ž ๊ฒจ์ ธ ์žˆ๋Š” ์ƒํƒœ๋กœ, ํ•ด๋‹น ์ž์›์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
2. ์ž ๊ธˆ ํ•ด์ œ(Unlocked) ์ƒํƒœ: ๋ฎคํ…์Šค๊ฐ€ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ์— ์˜ํ•ด ์ž ๊ธˆ ํ•ด์ œ๋˜์–ด ํ•ด๋‹น ์ž์›์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ์ƒํƒœ์ž…๋‹ˆ๋‹ค.

๋ฎคํ…์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ผ๋ฐ˜์ ์ธ ํŒจํ„ด์€ ์Šค๋ ˆ๋“œ๊ฐ€ ์ž์›์— ์ ‘๊ทผํ•˜๊ธฐ ์ „์— ๋ฎคํ…์Šค๋ฅผ ํ†ตํ•ด Lock์„ ๊ฑธ๊ณ , ์ž์›์„ ์‚ฌ์šฉํ•œ ํ›„์— ์ž ๊ธˆ ํ•ด์ œ(Unlock) ์ƒํƒœ๋กœ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ์ ‘๊ทผ ๋ฐฉ์‹์œผ๋กœ ๋ฎคํ…์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๋งŒ์ด ์ž์›์— ์ ‘๊ทผํ•˜๊ฒŒ ๋˜๋ฏ€๋กœ ๊ฒฝ์Ÿ์ƒํƒœ(Race Condition)๋‚˜ ๋ฐ๋“œ๋ฝ(Deadlock) ๋“ฑ์˜ ๋ฌธ์ œ๋ฅผ ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


 

 

์กฐ๊ฑด๋ณ€์ˆ˜(condition_variable)

std::condition_variable์€ C++ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๋™๊ธฐํ™” ๊ธฐ๋Šฅ ์ค‘ ํ•˜๋‚˜๋กœ, ์Šค๋ ˆ๋“œ ๊ฐ„์˜ ์ƒํ˜ธ์ž‘์šฉ๊ณผ ๋™๊ธฐํ™”๋ฅผ ์œ„ํ•ด ์‚ฌ์šฉ๋˜๋Š” ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค. ์ฃผ๋กœ ํŠน์ • ์กฐ๊ฑด์ด ๋งŒ์กฑ๋  ๋•Œ๊นŒ์ง€ ์Šค๋ ˆ๋“œ์˜ ๋Œ€๊ธฐ(wait) ๋ฐ ํ†ต์ง€(notify) ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜์—ฌ ์Šค๋ ˆ๋“œ๋“ค์ด ํšจ์œจ์ ์œผ๋กœ ํ˜‘๋ ฅํ•˜๊ณ  ์กฐ์ •ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.

std::condition_variable์„ ์‚ฌ์šฉํ•˜๋ฉด ์Šค๋ ˆ๋“œ๊ฐ€ ํŠน์ • ์กฐ๊ฑด์„ ๊ธฐ๋‹ค๋ฆฌ๋ฉฐ ๋Œ€๊ธฐํ•˜๋Š” ๋™์•ˆ, ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๊ฐ€ ๊ทธ ์กฐ๊ฑด์ด ๋งŒ์กฑ๋˜๋ฉด ๋Œ€๊ธฐ ์ค‘์ธ ์Šค๋ ˆ๋“œ๋ฅผ ๊นจ์šฐ๊ณ  ํ†ต์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Š” ์Šค๋ ˆ๋“œ ๊ฐ„์˜ ํšจ์œจ์ ์ธ ์ž‘์—… ๋ถ„๋ฐฐ์™€ ํ˜‘๋ ฅ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

std::condition_variable์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์ฃผ๋กœ ๋‘ ๊ฐ€์ง€ ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค:

1. ๋Œ€๊ธฐ(wait)ํ•˜๊ธฐ: ์Šค๋ ˆ๋“œ๊ฐ€ ํŠน์ • ์กฐ๊ฑด์„ ๋งŒ์กฑํ•  ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐํ•˜๋Š” ์ƒํƒœ๋กœ ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค. std::condition_variable ๊ฐ์ฒด์™€ ํ•จ๊ป˜ std::unique_lock์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฎคํ…์Šค์™€ ์—ฐ๊ณ„ํ•˜์—ฌ ๋Œ€๊ธฐ ์ƒํƒœ๋กœ ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค.

2. ํ†ต์ง€(notify)ํ•˜๊ธฐ: ํŠน์ • ์กฐ๊ฑด์ด ๋งŒ์กฑ๋˜์—ˆ์„ ๋•Œ, ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๋ฅผ ๋Œ€๊ธฐ ์ƒํƒœ์—์„œ ๊นจ์šฐ๊ณ  ์ž‘์—…์„ ๊ณ„์†ํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. notify_one ๋˜๋Š” notify_all ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋Œ€๊ธฐ ์ค‘์ธ ์Šค๋ ˆ๋“œ๋ฅผ ๊นจ์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์•„๋ž˜๋Š” std::condition_variable์„ ์‚ฌ์šฉํ•œ ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค:

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void workerThread() {
    std::this_thread::sleep_for(std::chrono::seconds(2));
    
    {
        std::unique_lock<std::mutex> lock(mtx);
        ready = true;
        std::cout << "Worker thread is ready." << std::endl;
    }
    
    cv.notify_one();
}

int main() {
    std::thread t(workerThread);

    {
        std::unique_lock<std::mutex> lock(mtx);
        cv.wait(lock, [] { return ready; });
        std::cout << "Main thread received notification." << std::endl;
    }

    t.join();

    return 0;
}



์ด ์˜ˆ์ œ์—์„œ workerThread๋Š” 2์ดˆ ํ›„์— ready ๋ณ€์ˆ˜๋ฅผ true๋กœ ์„ค์ •ํ•˜๊ณ , cv.notify_one()์„ ํ˜ธ์ถœํ•˜์—ฌ ๋Œ€๊ธฐ ์ค‘์ธ ์Šค๋ ˆ๋“œ๋ฅผ ๊นจ์šฐ๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. main ํ•จ์ˆ˜์—์„œ๋Š” cv.wait()์„ ํ˜ธ์ถœํ•˜์—ฌ ready ๋ณ€์ˆ˜์˜ ๋ณ€๊ฒฝ์„ ๊ธฐ๋‹ค๋ฆฐ ํ›„ ํ†ต์ง€๋ฅผ ๋ฐ›์•„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

 

์•„๋ž˜๋Š” condition_variable์˜ wait_for(๋Œ€๊ธฐ ์‹œ๊ฐ„ ์ง€์ •)๋ฅผ ์‚ฌ์šฉํ•œ ์˜ˆ์ œ์ž…๋‹ˆ๋‹ค.

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void workerThread() {
    std::this_thread::sleep_for(std::chrono::seconds(2));

    {
        std::unique_lock<std::mutex> lock(mtx);
        ready = true;
        std::cout << "Worker thread is ready." << std::endl;
    }

    cv.notify_one();
}

int main() {
    std::thread t(workerThread);

    {
        std::unique_lock<std::mutex> lock(mtx);
        if (cv.wait_for(lock, std::chrono::seconds(1), [] { return ready; })) {
            std::cout << "Main thread received notification." << std::endl;
        } else {
            std::cout << "Main thread timed out waiting for notification." << std::endl;
        }
    }

    t.join();

    return 0;
}

cv.wait_for() ํ•จ์ˆ˜๋Š” ๋Œ€๊ธฐ ์ค‘์ธ ์Šค๋ ˆ๋“œ๊ฐ€ ready ๋ณ€์ˆ˜๊ฐ€ true๋กœ ๋ณ€๊ฒฝ๋˜๊ฑฐ๋‚˜ ์ตœ๋Œ€ 1์ดˆ๊ฐ€ ๊ฒฝ๊ณผํ•  ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐํ•ฉ๋‹ˆ๋‹ค. ๊ฒฝ๊ณผํ•œ ์‹œ๊ฐ„์ด ๋Œ€๊ธฐ ์‹œ๊ฐ„์„ ์ดˆ๊ณผํ•˜๋ฉด cv.wait_for()๋Š” false๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ , ๊ทธ๋ ‡์ง€ ์•Š์€ ๊ฒฝ์šฐ์—๋Š” true๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด์„œ ๋Œ€๊ธฐ ์ค‘์ธ ์Šค๋ ˆ๋“œ๋ฅผ ๊นจ์šฐ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

 

 

std::async

std::async๋Š” C++ ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ ์ œ๊ณตํ•˜๋Š” ๋น„๋™๊ธฐ ์ž‘์—…์„ ์ƒ์„ฑํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ํ•จ์ˆ˜๋‚˜ ํ•จ์ˆ˜ ๊ฐ์ฒด๋ฅผ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰ํ•˜๋ฉฐ, ๋ณ„๋„์˜ ์Šค๋ ˆ๋“œ์—์„œ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๊ฑฐ๋‚˜ ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. std::async๋Š” ๊ฐ„๋‹จํ•œ ๋น„๋™๊ธฐ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜๋ฐ›์„ ๋•Œ ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

std::async ํ•จ์ˆ˜์˜ ๊ธฐ๋ณธ ํ˜•์‹์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

template <class Function, class... Args>
std::future<typename std::result_of<Function(Args...)>::type>
std::async(std::launch policy, Function&& f, Args&&... args);



std::async ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

1. std::launch ์—ด๊ฑฐํ˜•์„ ์ด์šฉํ•˜์—ฌ ์‹คํ–‰ ์ •์ฑ…์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ์ฃผ๋กœ std::launch::async๋‚˜ std::launch::deferred๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
   - std::launch::async: ์ƒˆ๋กœ์šด ์Šค๋ ˆ๋“œ์—์„œ ๋น„๋™๊ธฐ ์ž‘์—…์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
   - std::launch::deferred: ์ž‘์—…์„ ํ˜ธ์ถœํ•˜์ง€ ์•Š๊ณ  ๊ฒฐ๊ณผ๋ฅผ ์š”์ฒญํ•  ๋•Œ๊นŒ์ง€ ์ง€์—ฐ์‹œํ‚ต๋‹ˆ๋‹ค.

2. ๋น„๋™๊ธฐ๋กœ ์‹คํ–‰ํ•  ํ•จ์ˆ˜๋‚˜ ํ•จ์ˆ˜ ๊ฐ์ฒด๋ฅผ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

3. ํ•จ์ˆ˜์— ํ•„์š”ํ•œ ์ธ์ž๋“ค์„ ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.

std::async๋Š” ๋ฐ˜ํ™˜๊ฐ’์œผ๋กœ std::future ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š”๋ฐ, ์ด ๊ฐ์ฒด๋ฅผ ํ†ตํ•ด ๋น„๋™๊ธฐ ์ž‘์—…์˜ ์ƒํƒœ๋ฅผ ํ™•์ธํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ฐ„๋‹จํ•œ ์˜ˆ์ œ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด std::async๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ณด์—ฌ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

#include <iostream>
#include <future>

int add(int a, int b) {
    return a + b;
}

int main() {
    // ๋น„๋™๊ธฐ ์ž‘์—…์„ ์‹คํ–‰ํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ std::future๋กœ ๋ฐ›์Œ
    std::future<int> result = std::async(std::launch::async, add, 3, 5);

    // ๊ฒฐ๊ณผ๋ฅผ ์–ป๊ธฐ ์œ„ํ•ด wait ๋ฐ get์„ ์‚ฌ์šฉ
    result.wait();
    int sum = result.get();

    std::cout << "Sum: " << sum << std::endl;

    return 0;
}


 std::async๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ add ํ•จ์ˆ˜๋ฅผ ๋น„๋™๊ธฐ์ ์œผ๋กœ ์‹คํ–‰ํ•˜๊ณ , ๊ฒฐ๊ณผ๋ฅผ ์–ป๊ธฐ ์œ„ํ•ด std::future์˜ wait์™€ get ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. std::launch::async๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ƒˆ๋กœ์šด ์Šค๋ ˆ๋“œ์—์„œ ์ž‘์—…์„ ์‹คํ–‰ํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

์ข€๋” ๋ณต์žกํ•œ ์˜ˆ์ œ๋ฅผ ๋ณด์‹œ์ฃ .

#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <future>

int parallelSum(const std::vector<int>& data, size_t chunkSize) {
    std::vector<std::future<int>> futures;

    // ๋ฒกํ„ฐ๋ฅผ chunkSize๋งŒํผ ๋‚˜๋ˆ„์–ด ๋ณ‘๋ ฌ๋กœ ํ•ฉ์‚ฐ ์ž‘์—… ์ˆ˜ํ–‰
    for (size_t i = 0; i < data.size(); i += chunkSize) {
        auto chunkBegin = data.begin() + i;
        auto chunkEnd = chunkBegin + chunkSize;

        futures.push_back(std::async(std::launch::async,
                                     [](std::vector<int>::const_iterator begin, std::vector<int>::const_iterator end) {
                                         return std::accumulate(begin, end, 0);
                                     },
                                     chunkBegin, chunkEnd));
    }

    // ๊ฐœ๋ณ„ ์ž‘์—… ๊ฒฐ๊ณผ๋ฅผ ๋ชจ๋‘ ํ•ฉ์‚ฐ
    int totalSum = 0;
    for (auto& future : futures) {
        totalSum += future.get();
    }

    return totalSum;
}

int main() {
    std::vector<int> data(10000);
    std::iota(data.begin(), data.end(), 1); // 1๋ถ€ํ„ฐ 10000๊นŒ์ง€์˜ ์ˆ˜๋กœ ์ฑ„์›€

    const size_t chunkSize = 1000;
    int sum = parallelSum(data, chunkSize);

    std::cout << "Parallel Sum: " << sum << std::endl;

    return 0;
}

๋ฒกํ„ฐ์˜ ์›์†Œ๋“ค์„ ๋ณ‘๋ ฌ๋กœ ํ•ฉ์‚ฐํ•˜๋Š” ์ž‘์—…์ž…๋‹ˆ๋‹ค. ๋ฒกํ„ฐ๋ฅผ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ฒญํฌ(chunk)๋กœ ๋‚˜๋ˆ„์–ด ๊ฐ ์ฒญํฌ๋ฅผ ๋ณ„๋„์˜ ์Šค๋ ˆ๋“œ์—์„œ ํ•ฉ์‚ฐํ•˜๊ณ , ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ชจ๋‘ ํ•ฉ์‚ฐํ•˜์—ฌ ๋ณ‘๋ ฌ ํ•ฉ์‚ฐ์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ ์ฒญํฌ๋ฅผ ๋ณ„๋„์˜ std::async ์ž‘์—…์œผ๋กœ ์‹คํ–‰ํ•˜๋ฉฐ, std::accumulate๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ ์ฒญํฌ์˜ ํ•ฉ์„ ๊ณ„์‚ฐํ•ฉ๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ ๋ชจ๋“  ์ž‘์—…์˜ ๊ฒฐ๊ณผ๋ฅผ ํ•ฉ์‚ฐํ•˜์—ฌ ์ตœ์ข… ๊ฒฐ๊ณผ๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค.

 

std::async๋Š” ์ž‘์—…(task)๊ธฐ๋ฐ˜ ์ ‘๊ทผ์ด๋ฉฐ std::thread๋Š” ์Šค๋ ˆ๋“œ(thread)๊ธฐ๋ฐ˜ ์ ‘๊ทผ ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ์ € ๊ฐ™์€ ๊ฒฝ์šฐ, ๋ฒ”์šฉ์ ์ธ ๊ฒฝ์šฐ์—๋Š” std::async๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ, ์Šค๋ ˆ๋“œ์˜ ์ž‘์—…์„ ํŠน์ˆ˜ํ•˜๊ณ  ์„ธ์„ธํ•˜๊ฒŒ ์กฐ์ •ํ•˜๊ฑฐ๋‚˜ ์Šค๋ ˆ๋“œํ’€์„ ๋งŒ๋“ค ๊ฒฝ์šฐ์—๋Š” std::thread๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

Effective c++์—์„œ๋„ std::async๋ฅผ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ์ด์œ ๋Š”, std::async๋Š” OS ๋‚ด๋ถ€์—์„œ Thread Pool์„ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋งŽ์€ ๋ฆฌ์†Œ์Šค๋ฅผ ์š”๊ตฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ thread์™€ ๋‹ฌ๋ฆฌ return๊ฐ’์ด ์žˆ์–ด์„œ ์ด๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ๊ณผ ์˜ˆ์™ธ์ฒ˜๋ฆฌ๊ฐ€ ๋” ํšจ์œจ์ ์ด๋ผ๋Š” ๊ฒƒ์ด ์žฅ์ ์ž…๋‹ˆ๋‹ค.

 

 

 

๋งˆ๋ฌด๋ฆฌ

ํ˜„์—…์—์„œ๋Š” ๋ชจ๋“  C++๋กœ ๊ตฌ์„ฑ๋œ ์„œ๋ฒ„ ํ”„๋กœ๊ทธ๋žจ & ๋ฐ๋ชฌ ํ”„๋กœ๊ทธ๋žจ์€ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์ž…๋‹ˆ๋‹ค. ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ๋ฅผ ์ดํ•ดํ•˜๊ณ  ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๋Š” ๋Šฅ๋ ฅ์ด ๊ณ ๊ธ‰ ๊ฐœ๋ฐœ์ž๋กœ ๊ฐ€๊ธฐ ์œ„ํ•œ ํŒ๋ณ„ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค. ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ๋””๋ฒ„๊น…๋„ ์‰ฝ์ง€ ์•Š์œผ๋ฉฐ ์ง๊ด€์ ์ด์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋”๋ผ๋„ ์–ด๋–ป๊ฒŒ ํ˜๋Ÿฌ๊ฐ€๋Š”์ง€ ์ดํ•ดํ•˜๊ธฐ ์‰ฝ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ฐ๊ฐ์˜ ์Šค๋ ˆ๋“œ์˜ ๋™์ž‘๊ณผ ๊ณต์œ ์ž์› ๊ด€๋ฆฌ, ์Šค๋ ˆ๋“œ๋ผ๋ฆฌ์˜ ์ถฉ๋Œ์ƒํ™ฉ ๋“ฑ์„ ์šด์˜์ฒด์ œ์™€ ๋ฉ”๋ชจ๋ฆฌ ๊ด€์ ์—์„œ ์ดํ•ดํ•˜๋ ค๊ณ  ๋…ธ๋ ฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋Š” ๋Œ€๋ถ€๋ถ„ ๋ณ‘๋ ฌ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๊ธฐ ์œ„ํ•จ์ž…๋‹ˆ๋‹ค. ํ•œ๊บผ๋ฒˆ์— ๋งŽ์€ ์–‘์˜ ์ด๋ฒคํŠธ or ์ž‘์—…์ด ์žˆ์„ ๋•Œ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์Šค๋ ˆ๋“œ์—๊ฒŒ ๋ณ„๋„์˜ ์ž‘์—… ์ฒ˜๋ฆฌ๋ฅผ ๋งก๊น๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์Šค๋ ˆ๋“œ๋ผ๋ฆฌ ๊ณต์œ ํ•ด์•ผ ํ•˜๋Š” ์ž์›์ด ์žˆ์„ ๊ฒฝ์šฐ ์ ์ ˆํ•œ ์œ„์น˜์— mutex lock์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž์›์˜ ๋…์ ๊ถŒ์„ ๊ฐ€์ง€๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. mutex lock์œผ๋กœ ์Šค๋ ˆ๋“œ๊ฐ€ ์ž์›์„ ์ ์œ ํ•˜๋Š” ์‹œ๊ฐ„์ด ์งง์„ ์ˆ˜๋ก ์ฒ˜๋ฆฌ์†๋„๋Š” ์ฆ๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ๋ฌผ๋ก  lock์„ ์•ˆ์“ฐ๋Š” ๊ฒƒ์ด ์ œ์ผ ์ข‹๊ฒ ์ฃ .

 

์—ฌ๋Ÿฌ ๊ฐœ์˜ ์Šค๋ ˆ๋“œ์—๊ฒŒ ์ž‘์—… ์ฒ˜๋ฆฌ๋ฅผ ๋งก๊ธธ ๋•Œ condition_variable์˜ notify()๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์Šค๋ ˆ๋“œ๋“ค์€ ์ž‘์—…์ด ์—†์„ ๋•Œ wait์ƒํƒœ๋กœ ๋Œ€๊ธฐํ•˜๊ณ  ์žˆ๋‹ค๊ฐ€ ์ž‘์—…์ด ๋ชฐ๋ ธ์„ ๋•Œ, notify()๋ฅผ ํ†ตํ•ด wait์ƒํƒœ์—์„œ ๋ฒ—์–ด๋‚˜๊ณ  ์ •ํ•ด์ง„ ๋กœ์ง์„ ์ˆ˜ํ–‰ํ•˜๊ณ  ๋‹ค์‹œ wait์ƒํƒœ๋กœ ๋Œ์•„๊ฐ€๋Š” ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ผ๋ฐ˜์ ์ž…๋‹ˆ๋‹ค.

 

 

๋‹ค์Œ ํฌ์ŠคํŒ…์— ๋‚˜์˜ฌ "ํ”„๋กœ๋“€์„œ ์ปจ์Šˆ๋จธ ํŒจํ„ด"๊ณผ "์Šค๋ ˆ๋“œํ’€"์—์„œ ๋ชจ๋“  ๊ณผ์ •์˜ ์˜ˆ์ œ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 


 

 

๋Œ“๊ธ€