๐Ÿ’ฟ์šด์˜์ฒด์ œ(๋™๊ธฐํ™”, ์„ธ๋งˆํฌ์–ด)

12674 ๋‹จ์–ด OSOS

๐Ÿ’ฝ์šด์˜์ฒด์ œ(๋™๊ธฐํ™”, ์„ธ๋งˆํฌ์–ด, ๋ฐ๋“œ๋ฝ)

๋™๊ธฐํ™” ์ด์Šˆ(Synchronization) ์ด์Šˆ

์‚ฌ์ง„ ์ถœ์ฒ˜: https://solt.tistory.com/78

  • ๋™๊ธฐํ™”: ์ž‘์—…๋“ค ์‚ฌ์ด์— ์‹คํ–‰ ์‹œ๊ธฐ๋ฅผ ๋งž์ถ”๋Š” ๊ฒƒ
  • ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์ผํ•œ ์ž์›(๋ฐ์ดํ„ฐ) ์ ‘๊ทผ์‹œ ๋™๊ธฐํ™” ์ด์Šˆ ๋ฐœ์ƒ
    • ๋™์ผ ์ž์›์„ ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์‹œ ์ˆ˜์ •์‹œ, ๊ฐ ์Šค๋ ˆ๋“œ ๊ฒฐ๊ณผ์— ์˜ํ–ฅ์„ ์คŒ

๋™๊ธฐํ™” ์ด์Šˆ ์˜ˆ์ œ

import threading

g_count = 0

def thread_main():
    global g_count
    for i in range(1000000):
        g_count = g_count + 1 
    
threads = []
lock = threading.Lock()

for i in range(50):
    th = threading.Thread(target= thread_main)
    threads.append(th)

for th in threads:
    th.start()

for th in threads:
    th.join()

print('g_count = ', g_count)
  • ํŒŒ์ด์ฌ์—์„œ ์“ฐ๋ ˆ๋“œ๋ฅผ ํ†ต์ œํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ import ํ–ˆ๋‹ค.
  • g_count ๋ผ๋Š” ์ „์—ญ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•ด์ฃผ๊ณ 
  • 1๋ถ€ํ„ฐ 100๋งŒ๊นŒ์ง€ 1์”ฉ ๋”ํ•˜๋Š” ๋ฐ˜๋ณต๋ฌธ ํ•จ์ˆ˜(thread_main)๋ฅผ ์ •์˜ํ–ˆ๋‹ค
  • ํ”„๋ฆฐํŠธํ•ด๋ณด๋ฉด 5์ฒœ๋งŒ์ด ๋‚˜์˜ค์ง€ ์•Š๊ณ  ๋‹ค๋ฅธ ์ˆซ์ž๊ฐ€ ๋‚˜์˜จ๋‹ค.

์šด์˜์ฒด์ œ๊ฐ€ ์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ์„ํ•ด์„œ ๋ฐฑ๋งŒ์˜ ๋ฐ˜๋ณต๋ฌธ์ด ์‹คํ–‰๋˜๋‹ค๊ฐ€ ์“ฐ๋ ˆ๋“œ๊ฐ€ ์ค‘๊ฐ„์— ๋ฐ”๋€Œ์–ด์„œ ์ƒ๊ธฐ๋Š” ์ผ์ด๋‹ค.

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

import threading

g_count = 0

def thread_main():
    global g_count
    lock.acquire()
    for i in range(1000000):
        g_count = g_count + 1 
    lock.release()
    
threads = []
lock = 
for i in range(50):
    th = threading.Thread(target= thread_main)
    threads.append(th)

for th in threads:
    th.start()

for th in threads:
    th.join()

print('g_count = ', g_count)
  • lock.acquire()๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— ๋ฐ˜๋ณต๋ฌธ์— ์ ‘๊ทผํ•  ๋•Œ ํ•œ๊ฐœ์˜ ์Šค๋ ˆ๋“œ๋งŒ ์ ‘๊ทผํ•˜๊ณ  ๋‚˜๋จธ์ง€๋Š” ๋ชป์ ‘๊ทผํ•˜๊ฒŒ ํ•œ๋‹ค.

  • ๋ฐ˜๋ณต๋ฌธ์— ์ ‘๊ทผํ•œ ์Šค๋ ˆ๋“œ๊ฐ€ ๋‚˜์˜ค๋ฉด์„œ lock.release()ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•ด์„œ ๋‹ค์Œ ์Šค๋ ˆ๋“œ๊ฐ€ ๋ฐ˜๋ณต๋ฌธ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•œ๋‹ค.

๋™๊ธฐํ™” ์ด์Šˆ ํ•ด๊ฒฐ ๋ฐฉ์•ˆ

  • Mutual exclusion(์ƒํ˜ธ ๋ฐฐ์ œ)
  • ์“ฐ๋ ˆ๋“œ๋Š” ํ”„๋กœ์„ธ์Šค์˜ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ,
    • ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ๋ณ€๊ฒฝํ•˜๋Š” ๊ณต์œ ๋ณ€์ˆ˜์— ๋Œ€ํ•ด Exclusive Access ํ•„์š”
    • ์–ด๋Š ํ•œ ์Šค๋ ˆ๋“œ๊ฐ€ ๊ณต์œ  ๋ณ€์ˆ˜๋ฅผ ๊ฐฑ์‹ ํ•˜๋Š” ๋™์•ˆ ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— ์ ‘๊ทผํ•˜์ง€ ๋ชปํ•˜๋„๋ก ๋ง‰๋Š”๋‹ค.

Mutual exclusion(์ƒํ˜ธ ๋ฐฐ์ œ)

    lock.acquire()
    for i in range(1000000):
        g_count = g_count + 1 
    lock.release()
  • ๋ฐ˜๋ณต๋ฌธ์ด ์ž„๊ณ„์˜์—ญ(critical section)์ด๊ณ 
  • g_count += 1 ์ด ์ž„๊ณ„์ž์›(critical resource)์ด๋‹ค.

๋™๊ธฐํ™”์™€ ์„ธ๋งˆํฌ์–ด

Mutex์™€ ์„ธ๋งˆํฌ์–ด (Semaphore)

  • Critical Section(์ž„๊ณ„๊ตฌ์—ญ)์— ๋Œ€ํ•œ ์ ‘๊ทผ์„ ๋ง‰๊ธฐ ์œ„ํ•ด LOCKING ๋งค์ปค๋‹ˆ์ฆ˜์ด ํ•„์š”
    • Mutex(binary semaphore)
      : ์ž„๊ณ„๊ตฌ์—ญ์— ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๋งŒ ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ์Œ
    • Semaphore
      : ์ž„๊ณ„๊ตฌ์—ญ์— ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ์Œ
      : counter๋ฅผ ๋‘์–ด์„œ ๋™์‹œ์— ๋ฆฌ์†Œ์Šค์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ํ—ˆ์šฉ ๊ฐ€๋Šฅํ•œ ์Šค๋ ˆ๋“œ ์ˆ˜๋ฅผ ์ œ์–ด

์„ธ๋งˆํฌ์–ด(Semaphore)

  • P: ๊ฒ€์‚ฌ (์ž„๊ณ„์˜์—ญ์— ๋“ค์–ด๊ฐˆ ๋•Œ) -> lock.acquire()
    • S๊ฐ’์ด 1 ์ด์ƒ์ด๋ฉด, ์ž„๊ณ„ ์˜์—ญ ์ง„์ž… ํ›„, S๊ฐ’ 1 ์ฐจ๊ฐ (S๊ฐ’์ด 0์ด๋ฉด ๋Œ€๊ธฐ)
P(s): wait(S) {
		while s <= 0 // ๋Œ€๊ธฐ
        S--; // ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค ์ ‘๊ทผ ์ œํ•œ (1๊ฐ์†Œ)
        }
  • V: ์ฆ๊ฐ€(์ž„๊ณ„์˜์—ญ์—์„œ ๋‚˜์˜ฌ ๋•Œ) -> lock.release()
    • S๊ฐ’์„ 1๋”ํ•˜๊ณ , ์ž„๊ณ„ ์˜์—ญ์„ ๋‚˜์˜ด
V(S): signal(S) {
	s ++;  // ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค ์ ‘๊ทผ ํ—ˆ์šฉ (1์ฆ๊ฐ€)
    }
  • S: ์„ธ๋งˆํฌ์–ด ๊ฐ’ (์ดˆ๊ธฐ ๊ฐ’๋งŒํผ ์—ฌ๋Ÿฌ ํ”„๋กœ์„ธ์Šค๊ฐ€ ๋™์‹œ ์ž„๊ณ„ ์˜์—ญ ์ ‘๊ทผ ๊ฐ€๋Šฅ)

์„ธ๋งˆํฌ์–ด(Semaphore)- ๋ฐ”์œ ๋Œ€๊ธฐ

  • wait()์€ S๊ฐ€ 0์ด๋ผ๋ฉด, ์ž„๊ณ„์˜์—ญ์— ๋“ค์–ด๊ฐ€๊ธฐ ์œ„ํ•ด, ๋ฐ˜๋ณต๋ฌธ ์ˆ˜ํ–‰
    • ๋ฐ”์œ๋Œ€๊ธฐ, busy waiting -> ๋ฉˆ์ถค์ด ์—†๋‹ค. -> CPU์— ๋ถ€ํ•˜๋ฅผ ๊ฑธ๋ฆฌ๊ฒŒ ํ•จ
P(s): wait(S) {
		while s <= 0 // ๋Œ€๊ธฐ
        S--; // ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค ์ ‘๊ทผ ์ œํ•œ (1๊ฐ์†Œ)
        }

์„ธ๋งˆํฌ์–ด(Semaphore) - ๋Œ€๊ธฐํ

  • S๊ฐ€ ์Œ์ˆ˜์ผ ๊ฒฝ์šฐ, ๋ฐ”์œ ๋Œ€๊ธฐ ๋Œ€์‹ , ๋Œ€๊ธฐํ์— ๋„ฃ๋Š”๋‹ค.
wait(S) {
    	S->count--;
    if (S->count <= 0) {
    	add this process to S->queue; // ๋Œ€๊ธฐ 
        block() // ๋ธ”๋ก, sleap()
    }
}
  • wakeup() ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ๋Œ€๊ธฐํ์— ์žˆ๋Š” ํ”„๋กœ์„ธ์Šค ์žฌ์‹คํ–‰
signal(s) {
		S->count++;
    if (S->count >=1) {
        remove a process P form S->queue;
        wakeup(P) // ๊นจ์šฐ๊ธฐ
    }
}

์ฐธ๊ณ : ์ฃผ์š” ์„ธ๋งˆํฌ์–ด ํ•จ์ˆ˜(POSIX ์„ธ๋งˆํฌ์–ด)

  • sem_open(): ์„ธ๋งˆํฌ์–ด๋ฅผ ์ƒ์„ฑ
  • sem_wait(): ์ž„๊ณ„์˜์—ญ ์ ‘๊ทผ ์ „, ์„ธ๋งˆํฌ์–ด๋ฅผ ์ž ๊ทธ๊ณ , ์„ธ๋งˆํฌ์–ด๊ฐ€ ์ž ๊ฒจ์žˆ๋‹ค๋ฉด, ํ’€๋ฆด ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐ
  • sem_post(): ๊ณต์œ ์ž์›์— ๋Œ€ํ•œ ์ ‘๊ทผ์ด ๋๋‚ฌ์„ ๋•Œ ์„ธ๋งˆํฌ์–ด ์ž ๊ธˆ์„ ํ•ด์ œํ•œ๋‹ค.

์ข‹์€ ์›นํŽ˜์ด์ง€ ์ฆ๊ฒจ์ฐพ๊ธฐ