ํ”„๋กœ์„ธ์Šค ๋™๊ธฐํ™” ๋„๊ตฌ์— ๋Œ€ํ•ด ์•Œ์•„๋ณธ๋‹ค.

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

Semaphoresms ๊นƒ๋ฐœ์ด๋ผ๋Š” ๋„ค๋œ๋ž€๋“œ ๋‹จ์–ด์ด๋‹ค. ์˜›๋‚ ์—๋Š” ๊ธฐ์ฐป๊ธธ์—์„œ ๊ณต์œ ํ•˜๋Š” ๊ธธ์ด ์žˆ์„ ๋•Œ, ๊นƒ๋ฐœ ํ‘œ์‹์œผ๋กœ ์˜ค๊ณ ๊ฐ์˜ ์‹ ํ˜ธ๋ฅผ ์ฃผ๊ณ  ๋ฐ›์•˜๋‹ค. ์ด๋Ÿฌํ•œ ๋งฅ๋ฝ์—์„œ, Critical section์„ ์‚ฌ์šฉํ•˜๋Š” ์“ฐ๋ ˆ๋“œ์— ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์˜ ์ด๋ฆ„์œผ๋กœ ๋ถ™๊ฒŒ ๋˜์—ˆ๋‹ค.

์œ„์˜ ๊ทธ๋ฆผ์„ ๋ณด๋ฉด ๊ณต์œ ํ•˜๋Š” ๊ธฐ์ฐป๊ธธ์ด ํ•˜๋‚˜์ด๋‹ค. ์ด ๊ฒฝ์šฐ ๊ณต์œ  ์ž์›์ด 1์ด๋ผ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ํ•˜๋‚˜์˜ ๊ธฐ์ฐจ๊ฐ€ ์ง€๋‚˜๊ฐˆ ๋•Œ 1์„ ๊ฐ์†Œ์‹œํ‚ค๊ณ , ๋‹ค ์ง€๋‚˜๊ฐ„ ๋’ค์— 1์„ ์ฆ๊ฐ€์‹œํ‚ค๋Š” ์ผ์„ ๋ฐ˜๋ณตํ•œ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‹ค๋ฅธ ๊ธฐ์ฐจ๊ฐ€ ์ง€๋‚˜๊ฐ€๋ ค๊ณ  ํ•  ๋•Œ, Semaphore๊ฐ€ 0์ธ ๊ฒฝ์šฐ์—๋Š” ์ •์ง€ํ•˜๊ณ  1์ธ ๊ฒฝ์šฐ์— ์ˆœ์ฐจ์ ์œผ๋กœ ์ง€๋‚˜๊ฐ€๊ฒŒ ํ•˜๋ฉด ํ•ด๊ฒฐ๋œ๋‹ค. ์ด๋ ‡๊ฒŒ Semaphore๊ฐ€ 0, 1์ธ ๊ฒฝ์šฐ๋ฅผ Binary Semaphore๋ผ ํ•œ๋‹ค.

๊ณต์œ  ์ž์›์ด ๊ผญ 1๊ฐœ์ผ ํ•„์š”๋Š” ์—†๋‹ค. ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ž์›์ธ ์ƒํ™ฉ๋„ ์กด์žฌํ•œ๋‹ค. ๊ฐ€๋ น ์œ„์˜ ๊ธฐ์ฐจ ๊ทธ๋ฆผ์—์„œ ํ†ต๊ณผํ•ด์„œ ๊ฐˆ ์ˆ˜ ์žˆ๋Š” ๊ณต์œ  ๊ธฐ์ฐป๊ธธ์ด 5๊ฐœ๋ผ๋ฉด, ๊ณต์œ ์ž์›์€ 5์ด๋‹ค. ์ด๋Ÿฐ ๊ฒฝ์šฐ๋ฅผ counting semaphore๋ผ ํ•œ๋‹ค.

1. ๊ตฌํ˜„

์œ„์˜ ์˜ˆ์‹œ์—์„œ ๋ณด๋“ฏ, ๊นƒ๋ฐœ์€ ์ด ๋‘๊ฐ€์ง€๊ฐ€ ํ•„์š”ํ•˜๋‹ค. ์ง€๋‚˜๊ฐ€๋Š” ๊ฒฝ์šฐ์—๋Š” ๊ฐ์†Œ, ์ง€๋‚˜๊ฐ„ ๋’ค์—๋Š” ์ฆ๊ฐ€์ด๋‹ค. ์ดˆ๊ธฐ์—๋Š” P, V๋กœ ๋ถˆ๋ ธ๋‹ค.(๋„ค๋œ๋ž€๋“œ์—์„œ ๋งŒ๋“ค์–ด์ ธ ๋„ค๋œ๋ž€๋“œ์–ด์˜ ์•ฝ์ž์ด๋‹ค.) ํ˜„์žฌ์—๋Š” P๋Š” test๋ฅผ ์˜๋ฏธํ•˜๋ฉฐ acquire() ๋กœ ์‚ฌ์šฉํ•˜๊ณ , V๋Š” increment๋ฅผ ์˜๋ฏธํ•˜๋ฉฐ release() ๋กœ ์‚ฌ์šฉํ•œ๋‹ค. acquire()๋Š” ์ž์›์ด ์‚ฌ์šฉ๊ฐ€๋Šฅํ•œ์ง€ ํ™•์ธํ•˜๊ณ , ์‚ฌ์šฉ๊ฐ€๋Šฅํ•˜๋‹ค๋ฉด ์‚ฌ์šฉํ•˜๊ณ  ๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋ฉด ๋Œ€๊ธฐํ•œ๋‹ค. release()๋Š” ์ž์›์„ ๋‚ด๋†“๊ณ , ๋‹ค์Œ ์ž์›์„ ์‹คํ–‰์‹œํ‚จ๋‹ค.

์ž๋ฐ”๋ฅผ ํ†ตํ•ด ์„ธ๋งˆํฌ ๊ตฌ์กฐ๋ฅผ ๊ฐ„๋‹จํžˆ ์‚ดํŽด๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

class Semaphore {
  int value;      // number of permits
  Semaphore(int value) {
    // ...
  }
  void acquire() {
    value--;
    if (value < 0) {
      // add this process/thread to list
      // block
    }
  }
  void release() {
    value++;
    if (value <= 0) {
      // remove a process P from list
      // wakeup P
    }
  }
}

์œ„ ์ฝ”๋“œ์—์„œ acquire() ๋Š” value๊ฐ’์„ ๊ฐ์†Œ์‹œํ‚ค๊ณ  ๋งŒ์•ฝ value๊ฐ’์ด 0๋ณด๋‹ค ์ž‘์œผ๋ฉด(๊ฐ€์šฉ์ž์›์„ ๋ชจ๋‘ ์‚ฌ์šฉํ•จ) ์ด๋ฏธ ํ•ด๋‹น ์ž„๊ณ„๊ตฌ์—ญ์— ์–ด๋Š ํ”„๋กœ์„ธ์Šค๊ฐ€ ์กด์žฌํ•œ๋‹ค๋Š” ์˜๋ฏธ์ด๋ฏ€๋กœ ํ˜„์žฌ ํ”„๋กœ์„ธ์Šค๋Š” ์ ‘๊ทผํ•˜์ง€ ๋ชปํ•˜๋„๋ก ๋ง‰์•„์•ผํ•œ๋‹ค. ์ด๋ฅผ list๋ผ๋Š” ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ค„์— ์ถ”๊ฐ€ํ•œ ๋’ค block์„ ๊ฑธ์–ด์ค€๋‹ค.(list๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ํ๋กœ ๋˜์–ด์žˆ๋‹ค.)

release() ๋Š” value๊ฐ’์„ ์ฆ๊ฐ€์‹œํ‚ค๊ณ , ๋งŒ์•ฝ value๊ฐ’์ด 0๋ณด๋‹ค ๊ฐ™๊ฑฐ๋‚˜ ์ž‘์œผ๋ฉด ์ž„๊ณ„๊ตฌ์—ญ์— ์ง„์ž…ํ•˜๋ ค๊ณ  ๋Œ€๊ธฐํ•˜๋Š” ํ”„๋กœ์„ธ์Šค๊ฐ€ list์— ๋‚จ์•„์žˆ๋‹ค๋Š” ์˜๋ฏธ์ด๋ฏ€๋กœ ๊ทธ ์ค‘์—์„œ ํ•˜๋‚˜๋ฅผ ๊บผ๋‚ด์–ด ์ž„๊ณ„๊ตฌ์—ญ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

์„ธ๋งˆํฌ๋ฅผ ๊ทธ๋ฆผ์œผ๋กœ ๋‚˜ํƒ€๋‚ด๋ฉด ์œ„์™€ ๊ฐ™๋‹ค. list๋Š” ์‹ค์ œ๋กœ ํ๋กœ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. acquire()์— ์˜ํ•ด block๋˜๋Š” ํ”„๋กœ์„ธ์Šค๋Š” ์„ธ๋งˆํฌ ๋‚ด๋ถ€์— ์žˆ๋Š” ํ์— ์‚ฝ์ž…๋œ ํ›„, ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ž„๊ณ„๊ตฌ์—ญ์„ ๋‚˜์˜ค๋ฉด์„œ release()๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์„ธ๋งˆํฌ ํ์— ์žˆ๋Š” ํ”„๋กœ์„ธ์Šค๋ฅผ ๊นจ์›Œ์•ผ ํ•œ๋‹ค.(๋‹ค์‹œ ready queue๋กœ ๋ณด๋‚ธ๋‹ค.)

์œ„์—์„œ ์‚ดํŽด๋ณธ ๊ฒƒ์ฒ˜๋Ÿผ ์„ธ๋งˆํฌ๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ Mutual exclusion์„ ์œ„ํ•ด ์‚ฌ์šฉ๋œ๋‹ค.
08. Process Synchronization

Bank Account Problem(์€ํ–‰ ๊ณ„์ขŒ ๋ฌธ์ œ) ํ•ด๊ฒฐ

์ด์ „ ๊ธ€์—์„œ ๋ณด์•˜๋˜ ์€ํ–‰ ๊ณ„์ขŒ ๋ฌธ์ œ์— ์„ธ๋งˆํฌ๋ฅผ ์ ์šฉํ•ด๋ณด์ž. ์œ„์—์„œ ์ž„๊ณ„๊ตฌ์—ญ์€ BankAccount ํด๋ž˜์Šค ๋‚ด๋ถ€์˜ ์ž…์ถœ๋ ฅํ•˜๋Š” ๋ถ€๋ถ„์ธ ๊ฒƒ์„ ๋ณด์•˜๋‹ค. ์—ฌ๊ธฐ์— ์„ธ๋งˆํฌ๋ฅผ ์ ์šฉํ•ด๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

import java.util.concurrent.Semaphore;  // ์„ธ๋งˆํฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ํŒŒ์ผ ๊ฐ€์žฅ ์œ„์— ์ถ”๊ฐ€ํ•ด์•ผ ํ•œ๋‹ค.
 
class BankAccount {
	int balance;
 
	Semaphore sem;
	BankAccount() {   // BankAccount ํด๋ž˜์Šค์˜ ์ƒ์„ฑ์ž๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด ์„ธ๋งˆํฌ๋ฅผ ๋งŒ๋“ ๋‹ค.
		sem = new Semaphore(1);  // value ๊ฐ’์„ 1๋กœ ์ดˆ๊ธฐํ™”ํ•œ๋‹ค.
	}
 
	void deposit(int amount) {
		try {
			sem.acquire();   // ์ž„๊ณ„๊ตฌ์—ญ์— ๋“ค์–ด๊ฐ€๊ธฐ๋ฅผ ์š”์ฒญํ•œ๋‹ค.
		} catch (InterruptedException e) {}
	    /* ์ž„๊ณ„ ๊ตฌ์—ญ */
		int temp = balance + amount;
		System.out.print("+");
		balance = temp;
 
		sem.release();   // ์ž„๊ณ„๊ตฌ์—ญ์—์„œ ๋‚˜๊ฐ„๋‹ค.
	}
	void withdraw(int amount) {
		try {
			sem.acquire();
		} catch (InterruptedException e) {}
	    /* ์ž„๊ณ„ ๊ตฌ์—ญ */
		int temp = balance - amount;
		System.out.print("-");
		balance = temp;
 
		sem.release();
	}
	int getBalance() {
		return balance;
	}
}

value ๊ฐ’์€ ์ž„๊ณ„๊ตฌ์—ญ์— ๋ช‡ ๊ฐœ์˜ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ ‘๊ทผํ•  ๊ฒƒ์ธ์ง€ ์ •ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™๋‹ค. ์ง€๊ธˆ์€ ์ž„๊ณ„ ๊ตฌ์—ญ์— ํ•˜๋‚˜์˜ ํ”„๋กœ์„ธ์Šค๋งŒ ์ ‘๊ทผ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— 1 ๋กœ ์ดˆ๊ธฐํ™” ํ•œ๋‹ค. (์œ„ ์ฝ”๋“œ๋ฅผ ์ œ์™ธํ•œ ๋ถ€๋ถ„์€ ๋™์ผํ•˜๋‹ค.) ์ด ์ฝ”๋“œ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜จ๋‹ค.

// +,- ์ถœ๋ ฅ ์ƒ๋žต
balance = 0

์ •์ƒ์ ์œผ๋กœ ์ž”์•ก์ด 0์›์ด ๋‚˜์˜จ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด ์ฝ”๋“œ๋Š” ์ž„๊ณ„๊ตฌ์—ญ์˜ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜์˜€์œผ๋ฏ€๋กœ ๋ช‡ ๋ฒˆ์„ ์ˆ˜ํ–‰ํ•˜์—ฌ๋„ ๊ฐ™์€ ๊ฒฐ๊ณผ๊ฐ’์ด ์ถœ๋ ฅ๋œ๋‹ค.

2. Ordering

์„ธ๋งˆํฌ๋Š” mutual exclusion๋ฟ ์•„๋‹ˆ๋ผ ordering์„ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋„ ์‚ฌ์šฉํ•œ๋‹ค. ์ฆ‰, ํ”„๋กœ์„ธ์Šค์˜ ์‹คํ–‰ ์ˆœ์„œ๋ฅผ ์›ํ•˜๋Š” ์ˆœ์„œ๋กœ ์„ค์ • ํ•  ์ˆ˜ ์žˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ํ”„๋กœ์„ธ์Šค๊ฐ€ P1, P2 ๋‘ ๊ฐœ๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜์ž. ์›ํ•˜๋Š” ์ˆœ์„œ๋Š” P1, P2 ์ˆœ์œผ๋กœ ์‹คํ–‰ํ•˜๊ธฐ๋ฅผ ์›ํ•œ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์„ค์ •ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.

// ์ดˆ๊ธฐ semaphore ๊ฐ’ = 0
sem value = 0

|P1|P2| |::|::| ||sem.acquire()| |section 1|section 2| |sem.release()||

P1์ด ๋จผ์ € ์‹คํ–‰๋œ ๊ฒฝ์šฐ

  1. Section 1 ์ด์ „์— ์•„๋ฌด๋Ÿฐ ๋™์ž‘์ด ์—†์œผ๋ฏ€๋กœ ๋ฐ”๋กœ ์ˆ˜ํ–‰ํ•œ๋‹ค.
  2. sem.release() ๋ฅผ ๋งŒ๋‚˜๋ฉด value๊ฐ’์„ 1 ์ฆ๊ฐ€์‹œํ‚ค๊ณ , ์„ธ๋งˆํฌ ํ์— ์žˆ๋Š” ํ”„๋กœ์„ธ์Šค๋ฅผ ๊นจ์›Œ์ฃผ๋Š”๋ฐ ํ˜„์žฌ์—๋Š” ํ์— ํ”„๋กœ์„ธ์Šค๊ฐ€ ์—†์œผ๋ฏ€๋กœ ์•„๋ฌด ๋™์ž‘๋„ ํ•˜์ง€ ์•Š๋Š”๋‹ค.
  3. P2๊ฐ€ ์‹คํ–‰๋œ๋‹ค.
  4. P2์˜ sem.acquire() ๋ฅผ ๋งŒ๋‚˜๋ฉด ํ˜„์žฌ value๊ฐ’์€ 1์ด๊ณ  ์ด๋ฅผ 1๊ฐ์†Œ์‹œํ‚ค๋ฉด 0์ด ๋œ๋‹ค. value = 0์ด๋ฉด block์„ ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ, ๋ฌด์‚ฌํžˆ Section 2๊ฐ€ ์ˆ˜ํ–‰๋œ๋‹ค.

P2๊ฐ€ ๋จผ์ € ์‹คํ–‰๋œ ๊ฒฝ์šฐ

  1. Section 2 ์ด์ „์— sem.acquire() ๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ ์ด๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š”๋ฐ, ํ˜„์žฌ value๊ฐ’์€ 0์ด๊ณ  ์ด๋ฅผ 1 ๊ฐ์†Œ ์‹œํ‚ค๋ฉด -1 ์ด ๋œ๋‹ค. value๊ฐ’์ด ์Œ์ˆ˜๋ฉด ํ•ด๋‹น ํ”„๋กœ์„ธ์Šค๋ฅผ block์‹œํ‚จ๋‹ค.(์„ธ๋งˆํฌ ํ์— ์‚ฝ์ž…ํ•œ๋‹ค.)
  2. P1์ด ์‹คํ–‰๋˜๋ฉด Section 1์ด ๋ฐ”๋กœ ์ˆ˜ํ–‰๋œ๋‹ค.
  3. sem.release() ๋ฅผ ๋งŒ๋‚˜๋ฉด value๊ฐ’์„ 1 ์ฆ๊ฐ€์‹œํ‚ค๊ณ , ์„ธ๋งˆํฌ ํ์— ์žˆ๋Š” P2 ํ”„๋กœ์„ธ์Šค๋ฅผ ๊นจ์›Œ์ค€๋‹ค.(ํ˜„์žฌ value = 0)
  4. P2์˜ Section 2๊ฐ€ ์ˆ˜ํ–‰๋œ๋‹ค.

์œ„์—์„œ ๋‘ ๊ฐ€์ง€ ๊ฒฝ์šฐ๋ฅผ ์‚ดํŽด๋ณด์•˜๋“ฏ์ด, P1, P2 ๋‘˜ ์ค‘ ์–ด๋Š ๊ฒƒ์„ ๋จผ์ € ์‹คํ–‰ํ•˜์—ฌ๋„ ๊ฒฐ๊ณผ์ ์œผ๋กœ P1 โ†’ P2 ์ˆœ์„œ๋กœ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

์ž…๊ธˆ ์ถœ๊ธˆ ์ˆœ์„œ๋กœ ์€ํ–‰๊ณ„์ขŒ ๋ฌธ์ œ ํ•ด๊ฒฐํ•˜๊ธฐ

์œ„์—์„œ ๊ณ„์† ์‚ดํŽด๋ดค๋˜ ์€ํ–‰๊ณ„์ขŒ ๋ฌธ์ œ์—์„œ ordering์„ ์ ์šฉํ•ด๋ณด์ž. ํ”„๋กœ์„ธ์Šค์˜ ์‹คํ–‰ ์ˆœ์„œ๋Š” ๋ฐ˜๋“œ์‹œ ์ž…๊ธˆ, ์ถœ๊ธˆ ์ˆœ์„œ๋กœ ์ˆ˜ํ–‰ํ•ด์•ผํ•œ๋‹ค.

class BankAccount {
	int balance;
 
	Semaphore sem, semOrder;
	BankAccount() {
		sem = new Semaphore(1);
		semOrder = new Semaphore(0);   // Ordeing์„ ์œ„ํ•œ ์„ธ๋งˆํฌ
	}
 
	void deposit(int amount) {
		try {
			sem.acquire();
		} catch (InterruptedException e) {}
		int temp = balance + amount;
		System.out.print("+");
		balance = temp;
		sem.release();
		semOrder.release();   // block๋œ ์ถœ๊ธˆ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์žˆ๋‹ค๋ฉด ๊นจ์›Œ์ค€๋‹ค.
	}
	void withdraw(int amount) {
		try {
			semOrder.acquire();   // ์ถœ๊ธˆ์„ ๋จผ์ €ํ•˜๋ ค๊ณ  ํ•˜๋ฉด blockํ•œ๋‹ค.
			sem.acquire();
		} catch (InterruptedException e) {}
		int temp = balance - amount;
		System.out.print("-");
		balance = temp;
		sem.release();
	}
	int getBalance() {
		return balance;
	}
}

์œ„์ฒ˜๋Ÿผ ์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. Ordering์„ ์œ„ํ•œ semOrder ์„ธ๋งˆํฌ ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•˜๊ณ , ์ถœ๊ธˆํ•˜๋Š” ๋™์ž‘ ์•ž์— acquire(), ์ž…๊ธˆํ•˜๋Š” ๋™์ž‘ ๋’ค์— release() ๋ฅผ ์ถ”๊ฐ€ํ•˜์˜€๋‹ค.

+++++++++++++++++++++++++------------+++++-----++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++------------------------------------------
----------------------------------------
balance = 0

์‹คํ–‰ ๊ฒฐ๊ณผ๋Š” ์œ„์™€ ๊ฐ™๋‹ค. +(์ž…๊ธˆ)๊ฐ€ ๋งจ ์•ž์—์„œ ์‹คํ–‰ํ•œ ๋ชจ์Šต์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.(์ž…๊ธˆ, ์ถœ๊ธˆ ํšŸ์ˆ˜๋Š” 100๋ฒˆ์œผ๋กœ ์ค„์˜€๋‹ค.)

๋งŒ์•ฝ, ์ž…๊ธˆ, ์ถœ๊ธˆ, ์ž…๊ธˆ, ์ถœ๊ธˆ, โ€ฆ ๊ต๋Œ€๋กœ ์ถœ๋ ฅํ•˜๋„๋ก ํ•˜๋ ค๋ฉด ์„ธ๋งˆํฌ๋ฅผ ๋‘ ๊ฐœ ์‚ฌ์šฉํ•˜์—ฌ ์•„๋ž˜์™€ ๊ฐ™์ด ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

void deposit(int amount) {
	try {
		sem.acquire();
		int temp = balance + amount;
		System.out.print("+");
		balance = temp;
		sem.release();
		semWithraw.release();
		semDeposit.acquire();   // ์ž…๊ธˆํ›„์—๋Š” ๋ฐ˜๋“œ์‹œ ์ถœ๊ธˆ์„ ํ•ด์•ผ ํ•˜๋ฏ€๋กœ ์ž์‹ ์„ blockํ•œ๋‹ค.
	} catch (InterruptedException e) {}
}
void withdraw(int amount) {
	try {
		semWithraw.acquire();  // ์ž…๊ธˆ๋ณด๋‹ค ๋จผ์ € ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์„ ๋ง‰๋Š”๋‹ค.
		sem.acquire();
	} catch (InterruptedException e) {}
	int temp = balance - amount;
	System.out.print("-");
	balance = temp;
	sem.release();
	semDeposit.release();  // ์ถœ๊ธˆ ์ˆ˜ํ–‰์ด ์™„๋ฃŒ๋˜๋ฉด block๋˜์—ˆ๋˜ ์ž…๊ธˆ ํ”„๋กœ์„ธ์Šค๋ฅผ ๊นจ์›Œ์ค€๋‹ค.
}
int getBalance() {
	return balance;
}
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
balance = 0

Reference