ํํ๊ฒ ์ฌ์ฉ๋๋ ์๋ฃ ๊ตฌ์กฐ์์ ๋ฝ์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์ดํด๋ณด์. ์๋ฃ ๊ตฌ์กฐ์ ๋ฝ์ ์ถ๊ฐํ์ฌ ์ฐ๋ ๋๊ฐ ์ฌ์ฉํ ์ ์๋๋ก ๋ง๋ค๋ฉด ๊ทธ ๊ตฌ์กฐ๋ thread safeํ๋ค๊ณ ํ ์ ์๋ค.
ํน์ ์๋ฃ ๊ตฌ์กฐ๊ฐ ์ฃผ์ด์ก์ ๋, ์ด๋ค ๋ฐฉ์์ผ๋ก ๋ฝ์ ์ถ๊ฐํด์ผ ๊ทธ ์๋ฃ ๊ตฌ์กฐ๊ฐ ์ ํํ๊ฒ ๋์ํ๊ฒ ๋ง๋ค ์ ์์๊น? ๋ ๋์๊ฐ ์๋ฃ ๊ตฌ์กฐ์ ๋ฝ์ ์ถ๊ฐํ์ฌ ์ฌ๋ฌ ์ฐ๋ ๋๊ฐ ๊ทธ ์๋ฃ ๊ตฌ์กฐ๋ฅผ ๋์ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋๋ก ํ๋ฉด (๋ณํ์ฑ) ๊ณ ์ฑ๋ฅ์ ์ป๊ธฐ ์ํด ๋ฌด์์ ํด์ผ ํ ๊น?
1. ๋ณํ ์นด์ดํฐ
์นด์ดํฐ๋ ๊ฐ์ฅ ๊ฐ๋จํ ์๋ฃ ๊ตฌ์กฐ ์ค ํ๋์ด๋ค. ๋ณํ์ด ๋ถ๊ฐ๋ฅํ ์นด์ดํฐ๋ฅผ ๋จผ์ ๋ณด์.
typedef struct _ _counter_t {
int value;
} counter_t;
void init(counter_t *c) {
cโ>value = 0;
}
void increment(counter_t *c) {
cโ>value++;
}
void decrement(counter_t *c) {
cโ>valueโโ;
}
int get(counter_t *c) {
return cโ>value;
}
๊ฐ๋จํ์ง๋ง ํ์ฅ์ฑ์ด ์์
์์์ ์ ์ํ ์นด์ดํฐ๋ฅด ์ด๋ป๊ฒ ํ๋ฉด thread safeํ๊ฒ ๋ง๋ค ์ ์์๊น?
typedef struct __counter_t {
int value;
pthread_mutex_t lock;
} counter_t;
void init(counter_t *c) {
cโ>value = 0;
Pthread_mutex_init(&cโ>lock, NULL);
}
void increment(counter_t *c) {
Pthread_mutex_lock(&cโ>lock);
cโ>value++;
Pthread_mutex_unlock(&cโ>lock);
}
void decrement(counter_t *c) {
Pthread_mutex_lock(&cโ>lock);
cโ>valueโโ;
Pthread_mutex_unlock(&cโ>lock);
}
int get(counter_t *c) {
Pthread_mutex_lock(&cโ>lock);
int rc = cโ>value;
Pthread_mutex_unlock(&cโ>lock);
return rc;
}
์ด ์นด์ดํฐ๋ ๊ฐ์ฅ ๊ฐ๋จํ๊ณ ๊ธฐ๋ณธ์ ์ธ ๋ณํ ์๋ฃ ๊ตฌ์กฐ์ ๋ณดํธ์ ์ธ ๋์์ธ ํจํด์ ๋ฐ๋ฅธ ๊ฒ์ด๋ค. ์๋ฃ ๊ตฌ์กฐ๋ฅผ ์กฐ์ํ๋ ๋ฃจํด์ ํธ์ถํ ๋ ๋ฝ์ ์ถ๊ฐํ์๊ณ , ๊ทธ ํธ์ถ๋ฌธ์ด ๋ฆฌํด๋ ๋ ๋ฝ์ด ํด์ ๋๋๋ก ํ์๋ค.
์ด ๋ฐฉ์์ Monitor๋ฅผ ์ฌ์ฉํ์ฌ ๋ง๋ ์๋ฃ ๊ตฌ์กฐ์ ์ ์ฌํ๋ค. ๋ชจ๋ํฐ ๊ธฐ๋ฒ์ ๊ฐ์ฒด์ ๋ํ ๋ฉ์๋๋ฅผ ํธ์ถํ๊ณ ๋ฆฌํดํ ๋ ์๋์ ์ผ๋ก ๋ฝ์ ํ๋ํ๊ณ ํด์ ํ๋ค.
์ด์ ์ ๋๋ก ๋์ํ๋ ๋ณํ ์๋ฃ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๊ฒ ๋์์ง๋ง, ์ฑ๋ฅ์ด ๋ฌธ์ ๋ค. ์ด๋ฒ ์ฅ์์๋ ์ฑ๋ฅ ์ต์ ํ๋ฅผ ๋ค๋ฃฐ ๊ฒ์ด๋ค.
๊ฐ ์ฐ๋ ๋๊ฐ ํน์ ํ์๋งํผ ๊ณต์ ์นด์ดํฐ๋ฅผ ์ฆ๊ฐ์ํค๋ ๋ฒค์น๋งํฌ๋ฅผ ์คํํ์๋ค.

1๊ฐ์์ 4๊ฐ์ ์ฐ๋ ๋๋ฅผ ์ฌ์ฉํ์ฌ ์นด์ดํฐ๋ฅผ ๋ฐฑ๋ง ๋ฒ ์ฆ๊ฐ์์ผฐ์ ๋ ์ด ๊ฑธ๋ฆฐ ์๊ฐ์ ๋ํ๋ธ ๊ฒ์ด๋ค. precise๋ผ๊ณ ํ์๋ ์ ์์ ๋๊ธฐํ๋ ์นด์ดํฐ์ ํ์ฅ์ฑ์ด ๋จ์ด์ง๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
์ด์์ ์ผ๋ก๋ ํ๋์ ์ฐ๋ ๋๊ฐ ํ๋์ CPU์์ ์์ ์ ๋๋ด๋ ๊ฒ์ฒ๋ผ ๋ฉํฐํ๋ก์ธ์์์ ์คํ๋๋ ์ฐ๋ ๋๋ค๋ ๋น ๋ฅด๊ฒ ์์ ์ ์ฒ๋ฆฌํ๊ณ ์ถ์ ๊ฒ์ด๋ค(์๋ฒฝํ ํ์ฅ์ฑ: perfect scaling).
ํ์ฅ์ฑ ์๋ ์นด์ดํ
ํ์ฅ ๊ฐ๋ฅํ ์นด์ดํฐ๊ฐ ์์ผ๋ฉด Linux์ ๋ช๋ช ์์ ์ ๋ฉํฐ์ฝ์ด ๊ธฐ๊ธฐ์์ ์ฌ๊ฐํ ํ์ฅ์ฑ ๋ฌธ์ ๋ฅผ ๊ฒช์ ์ ์๋ค๊ณ ํ๋ค.
์ฌ๋ฌ ๊ธฐ๋ฒ ์ค ํ๋์ธ ์์ฑํ ์นด์ดํฐ(sloppy counter) ๋ฅผ ์๊ฐํ๋ค.
์์ฑํ ์นด์ดํฐ๋ ํ๋์ ๋ ผ๋ฆฌ์ ์นด์ดํฐ๋ก ํํ๋๋๋ฐ, CPU ์ฝ์ด๋ง๋ค ์กด์ฌํ๋ ํ๋์ ๋ฌผ๋ฆฌ์ ์ธ ์ง์ญ ์นด์ดํฐ์ ํ๋์ ์ ์ญ ์นด์ดํฐ๋ก ๊ตฌ์ฑ๋์ด ์๋ค. ์ด๋ค ๊ธฐ๊ธฐ๊ฐ ๋ค ๊ฐ์ CPU๋ฅผ ๊ฐ์ง๊ณ ์๋ค๋ฉด ๊ทธ ์์คํ ์ ๋ค ๊ฐ์ ์ง์ญ ์นด์ดํฐ์ ํ๋์ ์ ์ญ ์นด์ดํฐ๋ฅผ ๊ฐ์ง๊ณ ์๋ ๊ฒ์ด๋ค. ์ด ์นด์ดํฐ๋ค ์ธ์๋, ์ง์ญ ์นด์ดํฐ๋ฅผ ์ํ ๋ฝ๋ค๊ณผ ์ ์ญ ์นด์ดํฐ๋ฅผ ์ํ ๋ฝ์ด ์กด์ฌํ๋ค.
๊ธฐ๋ณธ ๊ฐ๋ ์ ๋ค์๊ณผ ๊ฐ๋ค.
์ฐ๋ ๋๋ ์ง์ญ ์นด์ดํฐ๋ฅผ ์ฆ๊ฐ์ํจ๋ค. ์ด ์ง์ญ ์นด์ดํฐ๋ ์ง์ญ ๋ฝ์ ์ํด ๋ณดํธ๋๋ค. ๊ฐ CPU๋ ์ ๋ง๋ค ์ง์ญ ์นด์ดํฐ๋ฅผ ๊ฐ๊ธฐ ๋๋ฌธ์ CPU๋ค์ ๋ถ์ฐ๋์ด ์๋ ์ฐ๋ ๋๋ค์ ์ง์ญ ์นด์ดํฐ๋ฅผ ๊ฒฝ์ ์์ด ๊ฐฑ์ ํ ์ ์๋ค. ๊ทธ๋ฌ๋ฏ๋ก ์นด์ดํฐ ๊ฐฑ์ ์ ํ์ฅ์ฑ์ด ์๋ค.
์ฐ๋ ๋๊ฐ ์นด์ดํฐ์ ๊ฐ์ ์ฝ์ ์ ์๊ธฐ ๋๋ฌธ์ ์ ์ญ ์นด์ดํฐ๋ฅผ ์ต์ ์ผ๋ก ๊ฐฑ์ ํด์ผ ํ๋ค. ์ต์ ๊ฐ์ผ๋ก ๊ฐฑ์ ํ๊ธฐ ์ํด์ ์ง์ญ ์นด์ดํฐ์ ๊ฐ์ ์ฃผ๊ธฐ์ ์ผ๋ก ์ ์ญ ์นด์ดํฐ๋ก ์ ๋ฌ๋๋๋ฐ, ์ด๋ ์ ์ญ ๋ฝ์ ์ฌ์ฉํ์ฌ ์ง์ญ ์นด์ดํฐ์ ๊ฐ์ ์ ์ญ ์นด์ดํฐ์ ๊ฐ์ ๋ํ๊ณ , ๊ทธ ์ง์ญ ์นด์ดํฐ์ ๊ฐ์ 0์ผ๋ก ์ด๊ธฐํํ๋ค.
์ง์ญ์์ ์ ์ญ์ผ๋ก ๊ฐ์ ์ ๋ฌํ๋ ๋น๋๋ ์ ํด ๋์ ๊ฐ์ ์ํด์ ๊ฒฐ์ ๋๋ค. ์ ๊ฐ์ด ์์ ์๋ก ํ์ฅ์ฑ ์๋ ์นด์ดํฐ์ฒ๋ผ ๋์ํ๊ณ , ์ปค์ง์๋ก ์ ์ญ ์นด์ดํฐ์ ๊ฐ์ ์ค์ ๊ฐ๊ณผ ์ฐจ์ด๊ฐ ์๊ฒ ๋๋ค.

์ด ์์ ์์๋ ํ๊ณ์น๋ฅผ 5๋ก ์ค์ ํ๊ณ , 4๊ฐ์ CPU์ ๊ฐ๊ฐ์ ์ง์ญ ์นด์ดํฐ โฆ ๋ฅผ ๊ฐฑ์ ํ๋ ์ฐ๋ ๋๋ค์ด ์๋ค. ์ ์ญ ์นด์ดํฐ์ ๊ฐ ๋ ๋ํ๋ด์๋ค. ์ง์ญ ์นด์ดํฐ๊ฐ ํ๊ณ์น ์ ๋๋ฌํ๋ฉด ๊ทธ ๊ฐ์ ์ ์ญ ์นด์ดํฐ์ ๋ฐ์๋๊ณ ์ง์ญ ์นด์ดํฐ์ ๊ฐ์ ์ด๊ธฐํ๋๋ค.

๊ฐ์ด ๋ฎ๋ค๋ฉด ์ฑ๋ฅ์ด ๋ฎ์ ๋์ ์ ์ญ ์นด์ดํฐ์ ๊ฐ์ด ๋งค์ฐ ์ ํํด์ง๋ค. ๊ฐ์ด ๋๋ค๋ฉด ์ฑ๋ฅ์ ํ์ํ์ง๋ง ์ ์ญ ์นด์ดํฐ์ ๊ฐ์ CPU์ ๊ฐ์์ ์ ๊ณฑ๋งํผ ๋ค์ณ์ง๊ฒ ๋๋ค.
typedef struct __counter_t {
int global;
pthread_mutex_t glock;
int local[NUMCPUS];
pthread_mutex_t llock[NUMCPUS];
int threshold;
} counter_t;
void init(counter_t *c, int threshold) {
cโ>threshold = threshold;
cโ>global = 0;
pthread_mutex_init(&cโ>glock, NULL);
int i;
for (i = 0; i < NUMCPUS; i++) {
cโ>local[i] = 0;
pthread_mutex_init(&cโ>llock[i], NULL);
}
}
void update(counter_t *c, int threadID, int amt) {
pthread_mutex_lock(&cโ>llock[threadID]);
cโ>local[threadID] += amt;
if (cโ>local[threadID] >= cโ>threshold) {
pthread_mutex_lock(&cโ>glock);
cโ>global += cโ>local[threadID];
pthread_mutex_unlock(&cโ>glock);
cโ>local[threadID] = 0;
}
pthread_mutex_unlock(&cโ>llock[threadID]);
}
int get(counter_t *c) {
pthread_mutex_lock(&cโ>glock);
int val = cโ>global;
pthread_mutex_unlock(&cโ>glock);
return val;
}
2. ๋ณํ ์ฐ๊ฒฐ ๋ฆฌ์คํธ
์ด์ ์กฐ๊ธ ๋ ๋ณต์กํ ๊ตฌ์กฐ์ธ ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ฅผ ๋ค๋ค๋ณด์. ๊ฐ๋จํ๊ฒ ํ๊ธฐ ์ํด ๋ณํ ์ฝ์ ์ฐ์ฐ๋ง ์ดํด๋ณด๋๋ก ํ์.
typedef struct __node_t {
int key;
struct __node_t *next;
} node_t;
typedef struct __list_t {
node_t *head;
pthread_mutex_t lock;
} list_t;
void List_Init(list_t *L) {
Lโ>head = NULL;
pthread_mutex_init(&Lโ>lock, NULL);
}
int List_Insert(list_t *L, int key) {
pthread_mutex_lock(&Lโ>lock);
node_t *new = malloc(sizeof(node_t));
if (new == NULL) {
perror(โmalloc โ);
pthread_mutex_unlock(&Lโ>lock);
return โ1;
}
newโ>key = key;
newโ>next = Lโ>head;
Lโ>head = new;
pthread_mutex_unlock(&Lโ>lock);
return 0;
}
int List_Lookup(list_t *L, int key) {
pthread_mutex_lock(&Lโ>lock);
node_t *curr = Lโ>head;
while (curr) {
if (currโ>key == key) {
pthread_mutex_unlock(&Lโ>lock);
return 0;
}
curr = currโ>next;
}
pthread_mutex_unlock(&Lโ>lock);
return โ1;
}
์ฝ์ธ ์ฐ์ฐ์ ์์ํ๊ธฐ ์ ์ ๋ฝ์ ํ๋ํ๊ณ ๋ฆฌํด ์ง์ ์ ํด์ ํ๋ค. ๋งค์ฐ ๋๋ฌธ ๊ฒฝ์ฐ์ง๋ง malloc()์ด ์คํจํ ๊ฒฝ์ฐ์ ๋ฏธ๋ฌํ ๋ฌธ์ ๊ฐ ์๊ธธ ์ ์๋ค. ๊ทธ๋ฐ ๊ฒฝ์ฐ ์คํจ๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ ์ ๋ฝ์ ํด์ ํด์ผ ํ๋ค.
์ฝ์ ์ฐ์ฐ์ด ๋ณํํ์ฌ ์งํ๋๋ ์ํฉ์์ ์คํจ๋ฅผ ํ๋๋ผ๋ ๋ฝ ํด์ ๋ฅผ ํธ์ถํ์ง ์์ผ๋ฉด์ ์ฝ์ ๊ณผ ๊ฒ์์ด ์ฌ๋ฐ๋ฅด๊ฒ ๋์ํ๋๋ก ์์ ํ ์ ์์๊น? ์ฝ์ ์ฝ๋์์ ์๊ณ ์์ญ์ ์ฒ๋ฆฌํ๋ ๋ถ๋ถ๋ง ๋ฝ์ผ๋ก ๊ฐ์ธ๋๋ก ์ฝ๋ ์์๋ฅผ ๋ณ๊ฒฝํ๊ณ , ๊ฒ์ ์ฝ๋์ ์ข ๋ฃ๋ ๊ฒ์๊ณผ ์ฝ์ ๋ชจ๋ ๋์ผํ ์ฝ๋ ํจ์ค๋ฅผ ์ฌ์ฉํ ๋ก ํ ์ ์๋ค.
์ด ๋ฐฉ๋ฒ์ด ๋์ํ๋ ์ด์ ๋ ์ฝ๋ ์ผ๋ถ๋ ์ฌ์ค ๋ฝ์ด ํ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
malloc() ์์ฒด๊ฐ thread safeํ๋ค๋ฉด, ์ฐ๋ ๋๋ ์ธ์ ๋ ์ง ๊ฒฝ์ ์กฐ๊ฑด๊ณผ ๋ค๋ฅธ ๋ณํ์ฑ ๊ด๋ จ ๋ฒ๊ทธ๋ฅผ ๊ฑฑ์ ํ์ง ์์ผ๋ฉด์ ๊ฒ์ํ ์ ์๋ค. ๊ณต์ ๋ฆฌ์คํธ ๊ฐฑ์ ๋์๋ง ๋ฝ์ ํ๋ํ๋ฉด ๋๋ค.
ํ์ฅ์ฑ ์๋ ์ฐ๊ฒฐ ๋ฆฌ์คํธ
๋ณํ์ด ๊ฐ๋ฅํ ์ฐ๊ฒฐ ๋ฆฌ์คํธ๋ฅผ ๊ฐ๊ฒ ๋์์ง๋ง, ํ์ฅ์ฑ์ด ์ข์ง ์๋ค๋ ๋ฌธ์ ๊ฐ ์๋ค. ์ด๋ฅผ ํด๊ฒฐํด๋ณด์.
๋ณํ์ฑ์ ๊ฐ์ ํ๋ ๋ฐฉ๋ฒ ์ค ํ๋๋ก hand-over-hand locking(๋๋ lock coupling) ์ด๋ผ๋ ๊ธฐ๋ฒ์ ๊ฐ๋ฐํ๋ค.
๊ฐ๋ ์ ๋จ์ํ๋ค. ์ ์ฒด ๋ฆฌ์คํธ์ ํ๋์ ๋ฝ์ด ์๋ ๊ฒ์ด ์๋๋ผ ๊ฐ๋ณ ๋ ธ๋๋ง๋ค ๋ฝ์ ์ถ๊ฐํ๋ ๊ฒ์ด๋ค. ๋ฆฌ์คํธ๋ฅผ ์ํํ ๋ ๋ค์ ๋ ธ๋์ ๋ฝ์ ๋จผ์ ํ๋ํ๊ณ ์ง๊ธ ๋ ธ๋์ ๋ฝ์ ํด์ ํ๋๋ก ํ๋ค.
void List_Init(list_t *L) {
Lโ>head = NULL;
pthread_mutex_init(&Lโ>lock, NULL);
}
void List_Insert(list_t *L, int key) {
// ๋๊ธฐํ๋ฅผ ํ ํ์ ์์
node_t *new = malloc(sizeof(node_t));
if (new == NULL) {
perror(โmalloc โ);
return;
}
newโ>key = key;
// ์๊ณ ์์ญ๋ง ๋ฝ์ผ๋ก ๋ณดํธ
pthread_mutex_lock(&Lโ>lock);
newโ>next = Lโ>head;
Lโ>head = new;
pthread_mutex_unlock(&Lโ>lock);
}
int List_Lookup(list_t *L, int key) {
int rv = โ1;
pthread_mutex_lock(&Lโ>lock);
node_t *curr = Lโ>head;
while (curr) {
if (currโ>key == key) {
rv = 0;
break;
}
curr = currโ>next;
}
pthread_mutex_unlock(&Lโ>lock);
return rv; // ์ฑ๊ณต ํน์ ์คํจ
}
๋ฆฌ์คํธ ์ฐ์ฐ์ ๋ณํ์ฑ์ด ๋์์ง๊ธฐ ๋๋ฌธ์ ๊ด์ฐฎ์ ๊ฒ์ฒ๋ผ ๋ณด์ธ๋ค. ํ์ง๋ง, ๋ฆฌ์คํธ๋ฅผ ์ํํ ๋ ๊ฐ ๋ ธ๋์ ๋ฝ์ ํ๋ํ๊ณ ํด์ ํ๋ ์ค๋ฒํค๋๊ฐ ๋งค์ฐ ํฌ๊ธฐ ๋๋ฌธ์ ์๋ ๊ฐ์ ์ ๊ธฐ๋ํ๊ธฐ ์ฝ์ง ์๋ค.
๋ฝ ํ๋/ํด์ ์ ๊ฐ์ด ๋ถํ๊ฐ ํฐ ์ฐ์ฐ์ ์ถ๊ฐํ์ฌ ์๋ฃ ๊ตฌ์กฐ๋ฅผ ์ค๊ณํ๋ค๋ฉด, ๋ณํ์ฑ ์์ฒด๊ฐ ์ข์์ก๋ค๋ ๊ฒ์ ํฐ ์๋ฏธ๊ฐ ์๋ค. ์คํ๋ ค, ๋ถํ๊ฐ ํฐ ๋ฃจํด์ ๊ฑฐ์ ์ฌ์ฉํ์ง ์๋ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ด ๋ ์ข๋ค. ๋ฝ์ ๋ง์ด ์ถ๊ฐํ๊ณ ๋ณต์ก๋๊ฐ ์ฆ๊ฐํ๋ฉด ํฐ ๋จ์ ์ด ๋๋ค. ์ด๋ ๊ฒ์ด ๋ ์ข์์ง ์ ์ ์๋ ๋ฐฉ๋ฒ์ ๋ฑ ํ ๊ฐ์ง์ด๋ค. ๊ฐ๋จํ์ง๋ง ๋ณํ์ฑ์ด ๋จ์ด์ง๋ ๊ฒ๊ณผ ๋ณต์กํ์ง๋ง ๋ณํ์ฑ์ด ๋์ ๋ ๊ฒฝ์ฐ๋ฅผ ๋ค ๊ตฌํํ๊ณ ์ฑ๋ฅ์ ์ธก์ ํด ๋ณด์์ผ ํ๋ค. ์ฑ๋ฅ์ ์์ผ ์๋ ์์ง ์๋๊ฐ. ๊ฒฐ๊ณผ๋ โ์ข๋คโ, โ๋์๋คโ ๋ ์ค์ ํ๋์ผ ํ ๋๊น ๋ง์ด๋ค.
3. ๋ณํ ํ
typedef struct __node_t {
int value;
struct __node_t *next;
} node_t;
typedef struct __queue_t {
node_t *head;
node_t *tail;
pthread_mutex_t headLock;
pthread_mutex_t tailLock;
} queue_t;
void Queue_Init(queue_t *q) {
node_t *tmp = malloc(sizeof(node_t));
tmpโ>next = NULL;
qโ>head = qโ>tail = tmp;
pthread_mutex_init(&qโ>headLock, NULL);
pthread_mutex_init(&qโ>tailLock, NULL);
}
void Queue_Enqueue(queue_t *q, int value) {
node_t *tmp = malloc(sizeof(node_t));
assert(tmp != NULL);
tmpโ>value = value;
tmpโ>next = NULL;
pthread_mutex_lock(&qโ>tailLock);
qโ>tailโ>next = tmp;
qโ>tail = tmp;
pthread_mutex_unlock(&qโ>tailLock);
}
int Queue_Dequeue(queue_t *q, int *value) {
pthread_mutex_lock(&qโ>headLock);
node_t *tmp = qโ>head;
node_t *newHead = tmpโ>next;
if (newHead == NULL) {
pthread_mutex_unlock(&qโ>headLock);
return โ1;
}
*value = newHeadโ>value;
qโ>head = newHead;
pthread_mutex_unlock(&qโ>headLock);
free(tmp);
return 0;
}
4. ๋ณํ ํด์ ํ ์ด๋ธ
์ ์ฒด ์๋ฃ ๊ตฌ์กฐ์ ํ๋์ ๋ฝ์ ์ฌ์ฉํ ๊ฒ์ด ์๋๋ผ ํด์ ๋ฒ์ผ (๋ฆฌ์คํธ๋ก ๊ตฌํ๋์ด ์์) ๋ง๋ค ๋ฝ์ ์ฌ์ฉํ์ฌ์ ์ฑ๋ฅ์ด ์ฐ์ํ๋ค.
#define BUCKETS ()
typedef struct __hash_t {
list_t lists[BUCKETS];
} hash_t;
void Hash_Init(hash_t *H) {
int i;
for (i = ; i < BUCKETS; i++) {
List_Init(&Hโ>lists[i]);
}
}
int Hash_Insert(hash_t *H, int key) {
int bucket = key % BUCKETS;
return List_Insert(&Hโ>lists[bucket], key);
}
int Hash_Lookup(hash_t *H, int key) {
int bucket = key % BUCKETS;
return List_Lookup(&Hโ>lists[bucket], key);
}

5. ์์ฝ
๋ฝ ํ๋๊ณผ ํด์ ์ ์ฝ๋์ ํ๋ฆ์ ๋งค์ฐ ์ฃผ์๋ฅผ ๊ธฐ์ธ์ฌ์ผ ํ๋ค. ๋ณํ์ฑ ๊ฐ์ ์ด ๋ฐ๋์ ์ฑ๋ฅ ๊ฐ์ ์ผ๋ก ์ด์ด์ง๋ ๊ฒ์ ์๋๋ค. ์ฑ๋ฅ ๊ฐ์ ์ ์ฑ๋ฅ์ ๋ฌธ์ ๊ฐ ์๊ธธ ๊ฒฝ์ฐ์๋ง ํด๊ฒฐ์ฑ ์ ๊ฐ๊ตฌํด์ผ ํ๋ค.
๋ฝ์ ์ ํ ์ฌ์ฉํ์ง ์๋ ๋๊ธฐํ ๊ธฐ๋ฒ๋ค๋ ์ถํ์ ๋ค๋ฃฐ ๊ฒ์ด๋ค.