๋ณํ์ฑ ๋ฒ๊ทธ๋ ๋ช ๊ฐ์ ์ ํ์ ์ธ ํจํด์ ๊ฐ์ง๊ณ ์๋ค. ์ด๋ค ๊ฒฝ์ฐ๋ฅผ ํผํด์ผ ์ฌ๋ฐ๋ฅธ ๋ณํ ์ฝ๋๋ฅผ ์์ฑํ ์ ์๋์ง ์์๋ณด์
1. ์ค๋ฅ์ ์ข ๋ฅ
ํ๋ ์์ฉ ํ๋ก๊ทธ๋จ์๋ ์ด๋ค ๋ณํ์ฑ ์ค๋ฅ๊ฐ ์์๊น? ๋ค์์ Lu์ ์ฐ๊ตฌ ๊ฒฐ๊ณผ์ด๋ค.

์ด๋ฐ ์ข ๋ฅ์ ์ค๋ฅ (๋น ๊ต์ฐฉ ์ํ์ ๊ต์ฐฉ ์ํ) ๋ค์ ๋ํด ์ข ๋ ์์ธํ ์์๋ณด์.
2. ๋น ๊ต์ฐฉ ์ํ ์ค๋ฅ
Lu์ ์ฐ๊ตฌ ๊ฒฐ๊ณผ์ ๋ฐ๋ฅด๋ฉด, ๋น ๊ต์ฐฉ ์ํ ์ค๋ฅ๊ฐ ๋ณํ์ฑ ๊ด๋ จ ์ค๋ฅ์ ๊ณผ๋ฐ์๋ฅผ ์ฐจ์งํ๋ค. ๋น ๊ต์ฐฉ ์ํ ์ค๋ฅ์ ๋ถ๋ฅ ์ค ๋ํ์ ์ธ ์์์ฑ ์๋ฐ ์ค๋ฅ์ ์์ ์๋ฐ ์ค๋ฅ๋ฅผ ์ดํด๋ณด์.
์์์ฑ ์๋ฐ ์ค๋ฅ (atomicity violation)
์ฒซ ๋ฒ์งธ๋ก ๋ง๋๊ฒ ๋๋ ๋ฌธ์ ๋ ์์์ฑ ์๋ฐ ์ค๋ฅ์ด๋ค.
// Thread 1::
if (thdโ>proc_info) {
. . .
fputs(thdโ>proc_info, . . . ) ;
. . .
}
// Thread 2::
thdโ>proc_info = NULL;
์ด ์์ ์์ thd ์๋ฃ ๊ตฌ์กฐ์ proc_info ํ๋๋ฅผ ๋ ๊ฐ์ ๋ค๋ฅธ ์ฐ๋ ๋๊ฐ ์ ๊ทผํ๋ค. ์ฒซ ๋ฒ์งธ ์ฐ๋ ๋๋ ๊ทธ ๊ฐ์ด NULL์ธ์ง ๊ฒ์ฌํ๊ณ ๊ฐ์ ์ถ๋ ฅํ๋ค. ๋ ๋ฒ์งธ ์ฐ๋ ๋๋ ๊ฐ์ NULL์ผ๋ก ์ค์ ํ๋ค.
์ฒซ ๋ฒ์งธ ์ฐ๋ ๋๊ฐ ๊ฒ์ฌ๋ฅผ ์๋ฃํ ํ, fputs()๋ฅผ ํธ์ถํ๊ธฐ ์ง์ ์ ์ธํฐ๋ฝํธ๋ก ์ธํด ๋ ๋ฒ์งธ ์ฐ๋ ๋๊ฐ ์คํ๋์ด ๊ฐ์ด NULL๋ก ์ค์ ๋ ์ ์๋ค. ๋๋ฌธ์ fputs() ํจ์๋ NULL ํฌ์ธํฐ ์ญ์ฐธ์กฐ๋ฅผ ํ๊ฒ ๋์ด ํ๋ก๊ทธ๋จ์ ํฌ๋์๋ ๊ฒ์ด๋ค.
๋ค์์ ๋ฉ๋ชจ๋ฆฌ ์ฐธ์กฐ ์ฐ์ฐ๋ค ๊ฐ์ ์์ด ์์ํ๋ ์ง๋ ฌ์ฑ(serializability)์ด ๋ณด์ฅ๋์ง ์์๋ค. ์ฆ ์ฝ๋์ ์ผ๋ถ์ ์์์ฑ์ด ์๊ตฌ๋์์ผ๋, ์คํ ์์ ๊ทธ ์์์ฑ์ด ์๋ฐ๋์๋ค.
ํ์ฌ ์์ ์ฝ๋๋ proc_info ํ๋์ NULL ๊ฐ ๊ฒ์ฌ์ fputs() ํธ์ถ ์ proc_info๋ฅผ ์ธ์๋ก ์ฌ์ฉํ๋ ๋์์ด ์์์ ์ผ๋ก ์คํ๋๋ ๊ฒ (atomicity assumption)์ ๊ฐ์ ํ๋ค. ์ด ๊ฐ์ ์ด ๊นจ์ง๋ฉด, ์ฝ๋๋ ์๋ํ ๋๋ก ์๋ํ์ง ์๋๋ค.
์ฝ๋๋ฅผ ์ด๋ป๊ฒ ์์ ํ๋ฉด ์๋ํ ๊น? ๋ฝ์ ์ถ๊ฐํ์ฌ ์ด๋ ์ฐ๋ ๋๋ proc_info ํ๋ ์ ๊ทผ ์ proc_info_lock ์ด๋ผ๋ ๋ฝ ๋ณ์๋ฅผ ํ๋ํ๋๋ก ํ๋ค. ์ด ์๋ฃ ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํ๋ ๋ค๋ฅธ ๋ชจ๋ ์ฝ๋๋ค๋ ๋ฝ์ผ๋ก ๋ณดํธํด์ผ ํ๋ค.
pthread_mutex_t proc_info_lock = PTHREAD_MUTEX_INITIALIZER;
// Thread 1::
pthread_mutex_lock(&proc_info_lock);
if (thdโ>proc_info) {
. . .
fputs(thdโ>proc_info, . . . ) ;
. . .
}
pthread_mutex_unlock(&proc_info_lock);
// Thread 2::
pthread_mutex_lock(&proc_info_lock);
thdโ>proc_info = NULL;
pthread_mutex_unlock(&proc_info_lock);
์์ ์๋ฐ ์ค๋ฅ (order violation)
๋ค์์ ์์ ์๋ฐ ์ค๋ฅ์ด๋ค. ์๋ ์์ ์ฝ๋์์ ์ด๋ค ๋ถ๋ถ์ ์ค๋ฅ๊ฐ ์๋์ง ํ๋ฒ ์ฐพ์๋ณด์.
// Thread 1::
void init() {
. . .
mThread = PR_CreateThread(mMain, . . . ) ;
. . .
}
// Thread 2::
void mMain ( . . . ) {
. . .
mState = mThreadโ>State;
. . .
}
์ด ์ฝ๋์์ ์ฐ๋ ๋ 2์ ์ฝ๋๋ mThread ๋ณ์๊ฐ ์ด๋ฏธ ์ด๊ธฐํ + NULL์ด ์๋์ ๊ฐ์ ํ๊ณ ์๋ค. ํ์ง๋ง ๋ง์ฝ ์ฐ๋ ๋ 1์ด ๋จผ์ ์คํ๋์ง ์์๋ค๋ฉด, ์ฐ๋ ๋ 2๋ NULL ํฌ์ธํฐ๋ฅผ ์ฌ์ฉํ๊ธฐ ๋๋ฌธ์ ํฌ๋์ฌ๋ ๊ฒ์ด๋ค. ์ด๊ธฐํ๋์ง ์์ NULL์ด ์๋ ์์์ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์๋ฅผ ์ ๊ทผํ๊ฒ ๋๋ฉด ๋ ์ด์ํ ์ผ์ด ๋ฐ์ํ ๊ฒ์ด๋ค.
๋ ๊ฐ์ (๊ทธ๋ฃน์) ๋ฉ๋ชจ๋ฆฌ ์ฐธ์กฐ ๊ฐ์ ์์๊ฐ ๋ฐ๋์๋ค. ์ฆ, A๊ฐ ํญ์ B๋ณด๋ค ๋จผ์ ์คํ๋์ด์ผ ํ์ง๋ง ์คํ ์ค์ ๊ทธ ์์๊ฐ ์ง์ผ์ง์ง ์์๋ค.
์ด๋ฌํ ์ค๋ฅ๋ฅผ ์์ ํ๋ ๋ฐฉ๋ฒ์ ์์๋ฅผ ๊ฐ์ ํ๋ ๊ฒ์ด๋ค. ์์์ ๋ ผ์ํ๋, ์ปจ๋์ ๋ณ์๋ฅผ ๋์ ํด์ ์์๋ฅผ ๊ฐ์ ํด๋ณด์.
pthread_mutex_t mtLock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t mtCond = PTHREAD_COND_INITIALIZER;
int mtInit = 0;
// Thread 1::
void init() {
. . .
mThread = PR_CreateThread(mMain, . . . ) ;
// ์ฐ๋ ๋๊ฐ ์์ฑ๋์๋ค๋ ๊ฒ์ ์๋ฆฌ๋ ์๊ทธ๋ ์ ๋ฌ
pthread_mutex_lock(&mtLock);
mtInit = 1;
pthread_cond_signal(&mtCond);
pthread_mutex_unlock(&mtLock);
. . .
}
// Thread 2::
void mMain ( . . . ) {
. . .
// ์ฐ๋ ๋๊ฐ ์ด๊ธฐํ๋๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆฐ๋ค
pthread_mutex_lock(&mtLock);
while (mtInit == 0)
pthread_cond_wait(&mtCond, &mtLock);
pthread_mutex_unlock(&mtLock);
mState = mThreadโ>State;
. . .
}
mtLock๋ผ๋ ๋ฝ, ๊ทธ์ ๋ํ ์ปจ๋์
๋ณ์ mtCond, ๊ทธ๋ฆฌ๊ณ ์ํ ๋ณ์ mtInit์ ์ถ๊ฐํ๋ค. ์ด๊ธฐํ ์ฝ๋๊ฐ ์คํ๋๋ฉด mtInit์ ์ํ๋ฅผ 1๋ก ์ค์ ํ๊ณ ์ด๊ธฐํ๋ฅผ ์๋ฃํ๋ค๊ณ ์๊ทธ๋์ ๋ฐ์์ํจ๋ค. ๋ง์ฝ ์ฐ๋ ๋ 2๊ฐ ์ด ์์ ์ ์ ์คํ๋๋ค๋ฉด ์ํ๊ฐ ๋ณ๊ฒฝ๋๊ธฐ๋ฅผ ๋๊ธฐํ๋ค. ์ดํ์ ๋ค์ ์ฐ๋ ๋ 2๊ฐ ์คํ๋๋ฉด ์ํ ๊ฐ ์ด๊ธฐํ ์ฌ๋ถ๋ฅผ ๊ฒ์ฌํ ํ, (mtInit์ด 1๋ก ์ค์ ๋์๋์ง ๊ฒ์ฌํ ํ) ์ฌ๋ฐ๋ฅด๊ฒ ๊ณ์ ์งํํ๋ค.
์ด๋ ๊ฒ ์ฐ๋ ๋ ๊ฐ์ ์์๊ฐ ๋ฌธ์ ๊ฐ ๋๋ ๊ฒฝ์ฐ๋ ์ปจ๋์ ๋ณ์ (๋๋ ์ธ๋งํฌ์ด) ๋ฅผ ์ฌ์ฉํ์ฌ ํด๊ฒฐํ ์ ์๋ค.
์ ๋ฆฌ
๋น ๊ต์ฐฉ ์ํ ์ค๋ฅ์ ๋๋ถ๋ถ(97%)์ ์์์ฑ ๋๋ ์์ ์๋ฐ์ ๋ํ ๊ฒ์ด์๋ค. ์ด๋ฌํ ์ค๋ฅ ํจํด๋ค์ ์ ์ํ๋ฉด ๊ด๋ จ ์ค๋ฅ๋ค์ ์ข ๋ ์ค์ผ ์ ์๋ค.
3. ๊ต์ฐฉ ์ํ ์ค๋ฅ
๋ณต์กํ ๋ฝ ํ๋กํ ์ฝ์ ์ฌ์ฉํ๋ ๋ค์์ ๋ณํ ์์คํ ์์ ๊ต์ฐฉ ์ํ(deadlock) ๋ผ๋ ๊ณ ์ ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค. ์๋ฅผ ๋ค์ด ๋ฝ L1์ ๊ฐ๊ณ ์๋ ์ฐ๋ ๋ 2๊ฐ ๋ฝ L1์ด ํด์ ๋๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆฌ๊ณ ์์ ๋ ๊ต์ฐฉ ์ํ๊ฐ ๋ฐ์ํ๋ค. ๊ต์ฐฉ ์ํ๊ฐ ๋ฐ์ํ ๊ฐ๋ฅ์ฑ์ด ์๋ ์ฝ๋๋ฅผ ๋ค์์ ๋ํ๋ด์๋ค.
Thread 1: Thread 2:
lock(L1); lock(L2);
lock(L2); lock(L1);
์ฐ๋ ๋ 1์ด ๋ฝ L1์ ํ๋ํ ํ์ ๋ฌธ๋งฅ ๊ตํ์ด ๋ฐ์ํ์ฌ ์ฐ๋ ๋ 2๊ฐ ์คํ๋๊ณ , ์ด ๋ ์ฐ๋ ๋ 2๊ฐ ๋ฝ L2๋ฅผ ํ๋ํ๊ณ ๋ฝ L1์ ํ๋ํ๋ ค๊ณ ์๋ํ๋ฉด ๊ต์ฐฉ ์ํ๊ฐ ๋ฐ์ํ๋ค.
๊ฐ ์ฐ๋ ๋๊ฐ ์๋๋ฐฉ์ด ์์ ํ๊ณ ์๋ ๋ฝ์ ๋๊ธฐํ๊ณ ์๊ธฐ ๋๋ฌธ์ ๋๊ตฌ๋ ์คํํ ์ ์๊ฒ ๋๋ค.

๊ต์ฐฉ ์ํ๋ ์ ๋ฐ์ํ๋๊ฐ
์ฐ๋ ๋ 1๊ณผ 2๊ฐ ๋ฝ์ ๊ฐ์ ์์๋ก ํ๋ํ๋๋ก ์ฝ๋๋ฅผ ์์ฑํ๋ฉด ๊ต์ฐฉ ์ํ๋ ์ ๋ ๋ฐ์ํ์ง ์๋๋ค. ์ด๋ ๊ฒ ๊ฐ๋จํ๊ฒ ํด๊ฒฐํ ์ ์๋๋ฐ ๊ต์ฐฉ ์ํ๋ ์ ๋ฐ์ํ ๊น?
์ฝ๋๊ฐ ๋ง์์ง๋ฉด์ ๊ตฌ์ฑ ์์ ๊ฐ์ ๋ณต์กํ ์์กด์ฑ์ด ๋ฐ์ํ๊ธฐ ๋๋ฌธ์ด๋ค. ์ด์์ฒด์ ๋ฅผ ์๋ก ๋ค๋ฉด, ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ ์์คํ ์ด ๋์คํฌ ๋ธ๋ญ์ ๊ฐ์ ธ์ค๊ธฐ ์ํด ํ์ผ ์์คํ ์ ์ ๊ทผํ๋ค. ํ์ผ ์์คํ ์ ๋์คํฌ ๋ธ๋ญ์ ๋ฉ๋ชจ๋ฆฌ์ ํ์ฌํ๊ธฐ ์ํด ๋ฉ๋ชจ๋ฆฌ ํ์ด์ง๋ฅผ ํ๋ณดํด์ผ ํ๊ณ , ์ด๋ฅผ ์ํด ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ ์์คํ ์ ์ ๊ทผํ๋ค.
๋ ๋ค๋ฅธ ์ด์ ๋ ์บก์ํ์ด๋ค. ์ํํธ์จ์ด ๋ชจ๋ํ๊ฐ ๊ฐ๋ฐ์ ์ฝ๊ฒ ํ๊ธฐ ๋๋ฌธ์ ์์ธํ ๊ตฌํ ๋ด์ฉ์ ๊ฐ์ถ๋๋ก ๊ตฌํํ๋ค. ํ์ง๋ง ์ด๋ฐ ๋ชจ๋ํ ๋๋ฌธ์ ๊ต์ฐฉ ์ํ๊ฐ ์ผ์ด๋ ์ ์๋ค.
์๋ฐ์ Vector ํด๋์ค๋ฅผ ์๋ก ๋ค๋ฉด,
Vector v1, v2;
v1.addAll(v2);
์ด ๋ฉ์๋๋ v1์ ๋ํ ๋ฝ ๋ฟ๋ง ์๋๋ผ v2์ ๋ํ ๋ฝ๋ ํ๋ํด์ผ ํ๋ค. ํ์ง๋ง ์ด๋ค ์ฐ๋ ๋๊ฐ v2.addAll(v1)์ ํธ์ถํ๋ฉด ๊ต์ฐฉ ์ํ๊ฐ ์ผ์ด๋ ์ ์๋ค.
๊ต์ฐฉ ์ํ ๋ฐ์ ์กฐ๊ฑด
๊ต์ฐฉ ์ํ๊ฐ ๋ฐ์ํ๊ธฐ ์ํด์๋ ๋ค ๊ฐ์ง ์กฐ๊ฑด์ด ์ถฉ์กฑ๋์ด์ผ ํ๋ค.
- ์ํธ ๋ฐฐ์ (Mutual Exclusion): ์ฐ๋ ๋๊ฐ ์์ ์ด ํ์๋ก ํ๋ ์์์ ๋ํ ๋ ์์ ์ธ ์ ์ด๊ถ์ ์ฃผ์ฅํ๋ค (์, ์ฐ๋ ๋๊ฐ ๋ฝ์ ํ๋ํจ).
- ์ ์ ๋ฐ ๋๊ธฐ (Hold-and-wait): ์ฐ๋ ๋๊ฐ ์์ ์๊ฒ ํ ๋น๋ ์์ (์ : ์ด๋ฏธ ํ๋ํ ๋ฝ)์ ์ ์ ํ ์ฑ๋ก ๋ค๋ฅธ ์์ (์ : ํ๋ํ๊ณ ์ ํ๋ ๋ฝ)์ ๋๊ธฐํ๋ค.
- ๋น ์ ์ (No preemption): ์์ (๋ฝ)์ ์ ์ ํ๊ณ ์๋ ์ฐ๋ ๋๋ก๋ถํฐ ์์์ ๊ฐ์ ์ ์ผ๋ก ๋นผ์์ ์ ์๋ค.
- ์ํ ๋๊ธฐ (Circular wait): ๊ฐ ์ฐ๋ ๋๋ ๋ค์ ์ฐ๋ ๋๊ฐ ์์ฒญํ ํ๋ ๋๋ ๊ทธ ์ด์์ ์์ (๋ฝ)์ ๊ฐ๊ณ ์๋ ์ฐ๋ ๋๋ค์ ์ํ ๊ณ ๋ฆฌ๊ฐ ์๋ค.
์ด ๋ค ์กฐ๊ฑด ์ค ํ๋๋ผ๋ ๋ง์กฑ์ํค์ง ์๋๋ค๋ฉด, ๊ต์ฐฉ ์ํ๋ ๋ฐ์ํ์ง ์๋๋ค.
๊ต์ฐฉ ์ํ์ ์๋ฐฉ
์ํ ๋๊ธฐ
๊ฐ์ฅ ์ค์ฉ์ ์ธ ๋ฐฉ๋ฒ์ด๋ฉด์ ์์ฃผ ์ฌ์ฉ๋๋ ๋ฐฉ๋ฒ์ ์ํ ๋๊ฐ๊ธฐ ์ ๋ ๋ฐ์ํ์ง ์๋๋ก ๋ฝ ์ฝ๋๋ฅผ ์์ฑํ๋ ๊ฒ์ด๋ค.
๋ฝ ํ๋์ ํ๋ ์ ์ฒด ์์ (total ordering) ์ ์ ํ ์ ์๋ค. L1๊ณผ L2๋ผ๋ ๋๊ฐ์ ๋ฝ๋ง์ด ์์คํ ์ ์กด์ฌํ๋ฉด, L1์ ๋ฌด์กฐ๊ฑด L2 ์ ์ ํ๋ํ๋๋ก ํ๋ฉด ๊ต์ฐฉ ์ํ๋ฅผ ํผํ ์ ์๋ค.
์ด ์์๋ฅผ ๋ฐ๋ฅด๋ฉด ์ํ ๋๊ธฐ๋ ๋ฐ์ํ์ง ์๊ณ , ๋ฐ๋ผ์ ๊ต์ฐฉ ์ํ๋ ๋ฐ์ํ์ง ์๋๋ค.
๋ณต์กํ ์์คํ ์ ๊ฒฝ์ฐ ๋ฝ์ด ์ฌ๋ฌ ๊ฐ ์กด์ฌํ ๊ฒ์ด๊ณ , ์ ์ฒด ๋ฝ์ ์์ฒญ ์์๋ฅผ ์ ์ํ๋ ๊ฒ์ด ์ด๋ ค์ธ ์ ์๋ค. (๋ถํ์ํ๊ธฐ๋ ํ๋ค) ๋๋ฌธ์ ๋ถ๋ถ ์์ (partial ordering) ์ ์ ๊ณตํ๋ ๊ฒ์ด ๋ฝ ํ๋ ๊ตฌ์กฐ๋ฅผ ๋ง๋๋ ๋ฐ ์ ์ฉํ๋ค.
๋ฝ์ ์์๋ฅผ ์ ์ํ๊ธฐ ์ํด์๋ ์ฝ๋์ ๋ค์ํ ๋ฃจํด ๊ฐ์ ์ํธ ํธ์ถ ๊ด๊ณ๋ฅผ ์ดํดํด์ผ ํ๋ค. ์กฐ๊ธ๋ง ์ค์ํด๋ ๊ต์ฐฉ ์ํ๊ฐ ๋ฐ์ํ๊ฒ ๋๋ค.
๋ฝ ์ฃผ์๋ฅผ ์ฌ์ฉํ์ฌ ๋ฝ ์์ฒญ ์์๋ฅผ ๊ฐ์ ํ๋ ๋ฐฉ๋ฒ๋ ์๋ค.
if (m1 > m2) { // ๋ฝ์ ์ฃผ์์ ๋ด๋ฆผ์ฐจ์์ผ๋ก ํ๋
pthread_mutex_lock(m1);
pthread_mutex_lock(m2);
} else {
pthread_mutex_lock(m2);
pthread_mutex_lock(m1);
}
// m1 != m2๋ฅผ ๊ฐ์
์ ์ ๋ฐ ๋๊ธฐ
์์์ ์ผ๋ก ๋ชจ๋ ๋ฝ์ ํ๋ฒ์ ํ๋ํ๋๋ก ํ๋ฉด ์ด๋ฅผ ์๋ฐฉํ ์ ์๋ค.
lock(prevention);
lock(L1);
lock(L2);
. . .
unlock(prevention);
์ ์ผ ๋จผ์ prevention ๋ฝ์ ํ๋ํ์ฌ ๋ฝ์ ํ๋ํ๋ ๊ณผ์ ์ค์ ์ฐ๋ ๋์ ๋ฌธ๋งฅ ๊ตํ์ด ๋ฐ์ํ๋ ๊ฒ์ ๋ฐฉ์งํ๊ณ , ๊ฒฐ๊ณผ์ ์ผ๋ก ๊ต์ฐฉ ์ํ์ ๋ฐ์ ๊ฐ๋ฅ์ฑ์ ์ฐจ๋จํ๋ค. ๋ค๋ฅธ ์ฐ๋ ๋๊ฐ L1๊ณผ L2๋ฅผ ๋ค๋ฅธ ์์๋ก ํ๋ํ๋ ค๊ณ ํด๋ ์๊ด ์๋ค. prevention ๋ฝ์ ์ด๋ฏธ ํ๋ํ ํ์ ๋๋จธ์ง ๋ฝ์ ์์ฒญํ๊ธฐ ๋๋ฌธ์ด๋ค.
์ด ํด๋ฒ์ ๋ฌธ์ ์ ์ด ๋ง๋ค. ์บก์ํ๊ฐ ์ด๋ ต๋ค. ํ์ํ ๋ฝ์ ์ ํํ ํ์ ํด์ผ ํ๊ณ , ๊ทธ ๋ฝ๋ค์ ๋ฏธ๋ฆฌ ํ๋ํด์ผ ํ๊ธฐ ๋๋ฌธ์ด๋ค. ๋ฝ์ด ์ค์ ํ์ํ ๋ ์์ฒญํ๋ ๊ฒ์ด ์๋๋ผ ๋ฏธ๋ฆฌ ๋ชจ๋ ๋ฝ์ ํ๋ฒ์ ํ๋ํ๊ธฐ ๋๋ฌธ์ ๋ณํ์ฑ์ด ์ ํ๋๋ ๋ฌธ์ ๋ ์๋ค.
๋น์ ์
์ผ๋ฐ์ ์ผ๋ก ๋ฝ์ ํด์ ํ๊ธฐ ์ ๊น์ง๋ ๋ฝ์ ๋ณด์ ํ๊ณ ์๋ ๊ฒ์ผ๋ก ๋ณด๊ธฐ ๋๋ฌธ์ ์ฌ๋ฌ ๋ฝ์ ํ๋ํ๋ ๊ฒ์๋ ๋ฌธ์ ์ ์์ง๊ฐ ๋ง๋ค. ์๋ํ๋ฉด ๋ฝ์ ์ด๋ฏธ ๋ณด์ ํ๊ณ ์๋ ์ฑ๋ก ๋ค๋ฅธ ๋ฝ์ ๋๊ธฐํ๊ธฐ ๋๋ฌธ์ด๋ค. ๋๋ฌธ์ ๋ง์ ์ฐ๋ ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ค์ ์ด๋ฌํ ์ํฉ์ ํผํ ์ ์๋๋ก ์ ์ฐํ ์ธํฐํ์ด์ค ์งํฉ์ ์ ๊ณตํ๋ค. trylock() ๋ฃจํด์ ๊ฒฝ์ฐ ํ๋ ๊ฐ๋ฅํ๋ค๋ฉด ๋ฝ์ ํ๋ํ๊ฑฐ๋ ํ์ฌ ๋ฝ์ด ์ ์ ๋ ์ํ์ด๋ ๋์ค์ ๋ค์ ์๋๋ผํ๋ผ๋ ๊ฒ์ ์๋ฆฌ๋ -1์ ๋ฆฌํดํ๋ค.
์ด trylock() ์ธํฐํ์ด์ค๋ฅผ ์ด์ฉํ๋ฉด ๊ต์ฐฉ ์ํ ๊ฐ๋ฅ์ฑ์ด ์๊ณ ํ๋ ์์์ ์ํฅ์ ๋ฐ์ง ์๋ ๋ฝ ํ๋ ๋ฐฉ๋ฒ์ ๋ง๋ค ์ ์๋ค.
top:
lock(L1);
if (trylock(L2) == โ1) {
unlock(L1);
goto top;
}
๋ค๋ฅธ ์ฐ๋ ๋๊ฐ ๊ฐ์ ํ๋กํ ์ฝ์ ์ฌ์ฉํ๋ฉด์ ๋ฝ์ ๋ค๋ฅธ ์์๋ก ํ๋ํ๋ ค๊ณ ํด๋ ๊ต์ฐฉ ์ํ๋ ๋ฐ์ํ์ง ์๋๋ค. ํ์ง๋ง ๋ฌดํ๋ฐ๋ณต(livelock) ๋ฌธ์ ๊ฐ ์๊ธด๋ค.
๋ ์ฐ๋ ๋๊ฐ ์ด ์์๋ก ๊ณ์ ์๋ํ๋ฉด์ ๋ฝ ํ๋์ ์คํจํ๋ ๊ฒ๋ ๊ฐ๋ฅํ๊ธด ํ๋ค. ํ๋ฅ ์ ๋ฎ์ง๋ง. ๋ฐ๋ณต๋ฌธ์ ์ง์ฐ ์๊ฐ์ ๋ฌด์์๋ก ์กฐ์ ํด์ ๊ฒฝ์ํ๋ ์ฐ๋ ๋ ๊ฐ์ ๋ฐ๋ณต ๊ฐ์ญ ํ๋ฅ ์ ์ค์ผ ์ ์๋ค.
์ํธ ๋ฐฐ์
๋ง์ง๋ง ์๋ฐฉ ๊ธฐ๋ฒ์ ์ํธ ๋ฐฐ์ ์์ฒด๋ฅผ ์์ ๋ ๋ฐฉ๋ฒ์ด๋ค. ์ผ๋ฐ์ ์ธ ์ฝ๋๋ ๋ชจ๋ ์๊ณ ์์ญ์ ํฌํจํ๊ณ ์๊ธฐ ๋๋ฌธ์ ์ด๋ ์ด๋ ค์ด ์ผ์ด๋ค.
wait free ์๋ฃ ๊ตฌ์กฐ๋ฅผ ๋ง๋ค์ด์ ์ด๋ฅผ ํด๊ฒฐํ๋ค. ๋ช ์์ ๋ฝ์ด ํ์ ์๋ ๊ฐ๋ ฅํ ํ๋์จ์ด ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํ์ฌ ์๋ฃ ๊ตฌ์กฐ๋ฅผ ๋ง๋ค๋ฉด ๋์ง ์์๊น?
๊ฐ๋จํ ์์ ๋ก Compare-And-Swap์ด ์๋ค.
int CompareAndSwap(int *address, int expected, int new) {
if (*address == expected) {
*address = new;
return 1; // ์ฑ๊ณต
}
return 0; // ์คํจ
}
์ด๋ค ํ ๊ฐ์ ์์์ ์ผ๋ก ์์์ ํฌ๊ธฐ๋งํผ ์ฆ๊ฐ์ํค๋ ๊ฒฝ์ฐ๋ฅผ ๊ตฌํํด๋ณด์.
void AtomicIncrement(int *value, int amount) {
do {
int old = *value;
} while (CompareAndSwap(value, old, old + amount) == 0);
}
๋ฝ์ ํ๋ํ์ฌ ๊ฐ์ ๊ฐฑ์ ํ ํ์ ๋ฝ์ ํด์ ํ๋ ๋์ , Compare-And-Swap ๋ช ๋ น์ด๋ก ๊ฐ์ ์๋ก์ด ๊ฐ์ ๊ฐฑ์ ํ๋๋ก ๋ฐ๋ณต์ ์ผ๋ก ์๋ํ๋ค. ์ด์ ๊ฐ์ ๋ฐฉ์์ ์ฌ์ฉํ๋ฉด ๋ฝ์ ํ๋ํ ํ์๊ฐ ์์ผ๋ฉฐ ๊ต์ฐฉ ์ํ๊ฐ ๋ฐ์ํ ์๋ ์๋ค. ๋ฌผ๋ก ๋ฌดํ ๋ฐ๋ณต์ ๋ฐ์ํ ์ฌ์ง๊ฐ ์๋ค.
์ข ๋ ๋ณต์กํ ์์ ๋ฅผ ๋ณด์. ๋ฆฌ์คํธ ํด๋์ ๊ฐ์ฒด๋ฅผ ์ฝ์ ํ๋ ์ฝ๋์ด๋ค.
void insert(int value) {
node_t *n = malloc(sizeof(node_t));
assert(n != NULL);
n->value = value;
do {
n->next = head;
} while (CompareAndSwap(&head, n->next, n) == 0);
}
next ํฌ์ธํฐ๊ฐ ํ์ฌ์ ํค๋๋ฅผ ๊ฐ๋ฆฌํค๋๋ก ๊ฐฑ์ ํ๊ณ , ์๋ก ์์ฑ๋ ๋
ธ๋๋ ๋ฆฌ์คํธ์ ํค๋๊ฐ ๋๋๋ก ๋์ํ๋ค. ์ด ์ฝ๋๋ฅผ ์ฒ๋ฆฌํ๋ ๋์ค ๋ค๋ฅธ ์ฐ๋ ๋๊ฐ ์๋ก์ด ํค๋๋ฅผ ์ถ๊ฐํ๋ค๋ฉด, Compare-And-Swap์ ์คํจํ๊ณ ์ฝ์
๊ณผ์ ์ ๋ค์ ์๋ํ๋ค.
์ค์ผ์ค๋ง์ผ๋ก ๊ต์ฐฉ ์ํ ํํผํ๊ธฐ
์๋ฐฉ๋ณด๋ค ํํผ๊ฐ ๋ ์ ์ฉํ ๋๊ฐ ์๋ค. ๊ต์ฐฉ ์ํ๋ฅผ ํํผํ๊ธฐ ์ํด์๋ ์ฌ๋ฌ ์ฐ๋ ๋๊ฐ ์ด๋ค ๋ฝ์ ํ๋ํ๊ฒ ๋ ๊ฒ์ธ์ง์ ๋ํด ์ ๋ฐ์ ์ผ๋ก ํ์ ํ๊ณ ์์ด์ผ ํ๋ฉฐ, ๊ทธ๊ฒ์ ๋ฐํ์ผ๋ก ์ฐ๋ ๋๋ค์ ์ค์ผ์ค๋งํ์ฌ ๊ต์ฐฉ ์ํ๊ฐ ๋ฐ์ํ์ง ์๋๋ก ๊ทธ๋๊ทธ๋ ๋ณด์ฅํ๋ค.

4๊ฐ์ ์ฐ๋ ๋๊ฐ ํ๋ก์ธ์ 2๊ฐ์์ ์คํ๋๊ณ , ๋ฝ 2๊ฐ๊ฐ ์กด์ฌํ๋ค๊ณ ๊ฐ์ ํ์. ๋๋ํ ์ค์ผ์ค๋ฌ๋ผ๋ฉด T1๊ณผ T2๊ฐ ๋์์ ์คํ๋์ง ์๋๋ก ํ์ฌ ๊ต์ฐฉ ์ํ๋ฅผ ํํผํ ๊ฒ์ด๋ค.

๋ค๋ฅธ ์์๋ ํ ๋ฒ ์ดํด๋ณด์.

์ด ๊ฒฝ์ฐ๋ T1, T2, T3์ด ๋์์ ์คํ๋๋ฉด ์ ๋๋ค.

T1, T2, T3์ด ๋ชจ๋ ํ ํ๋ก์ธ์์์ ์คํ๋๋๋ก ๋ณด์์ ์ธ ๋ฐฉ๋ฒ์ ํํ๊ธฐ ๋๋ฌธ์ ์ ์ฒด ์์ ์ด ๋๋๊ธฐ๊น์ง ์ค๋ ์๊ฐ์ด ๊ฑธ๋ฆฐ๋ค. ๋๋ฌธ์ ์ค์ผ์ค๋ง์ผ๋ก ๊ต์ฐฉ ์ํ๋ฅผ ํํผํ๋ ๊ฒ์ ๋ณดํธ์ ์ผ๋ก ์ฌ์ฉ๋๋ ๋ฐฉ๋ฒ์ ์๋๋ค.
๋ฐ๊ฒฌ ๋ฐ ๋ณต๊ตฌ
๋ง์ง๋ง ์ ๋ต์ ๊ต์ฐฉ ์ํ ๋ฐ์์ ํ์ฉํ๊ณ , ๋ฐ๊ฒฌํ๋ฉด ๋ณต๊ตฌํ๋๋ก ํ๋ ๋ฐฉ๋ฒ์ด๋ค. ์๋ฅผ ๋ค์ด ์ด์์ฒด์ ๊ฐ 1๋ ์ ํ ๋ฒ ๋ฉ์ถ๋ค๊ณ ํ์ ๋ ์์ํ๊ฒ ์ฌ๋ถํ ์ ํ๋ ๋ฐฉ๋ฒ์ด ์๋ค. ๊ต์ฐฉ ์ํ๊ฐ ์์ฃผ ๊ฐ๋ ๋ฐ์ํ๋ค๋ฉด ๊ฝค ์ ์ฉํ ๋ฐฉ๋ฒ์ด๋ค.
๋ง์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ์์คํ ๋ค์ด ๊ต์ฐฉ ์ํ๋ฅผ ๋ฐ๊ฒฌํ๊ณ ํ๋ณตํ๋ ๊ธฐ์ ์ ์ฌ์ฉํ๋ค. ์ด๋ ์ฃผ๊ธฐ์ ์ผ๋ก ์คํ๋๋ฉฐ ์์ ํ ๋น ๊ทธ๋ํ๋ฅผ ๊ทธ๋ ค์ ์ฌ์ดํด์ด ์๊ฒผ๋์ง๋ฅผ ๊ฒ์ฌํ๋ค. ์ฌ์ดํด์ด ๋ฐ์ํ๋ ๊ฒฝ์ฐ, ์์คํ ์ ์ฌ๋ถํ ๋์ด์ผ ํ๋ค.
ํญ์ ์๋ฒฝ์ ์ถ๊ตฌํ์ง๋ ๋ง์. ์ ์ข์ ์ผ์ด ์์ฃผ ๊ฐ๋ ๋ฐ์ํ๋ค๋ฉด, ๊ทธ ์ผ์ ๋ฐฉ์งํ๊ธฐ ์ํด์ ์์ฃผ ๋ง์ ์๊ฐ์ ๋ค์ผ ํ์๋ ์๋ค.