ํ˜„์žฌ ์‚ฌ์šฉํ•˜๋Š” ๋™๊ธฐํ™” ๋„๊ตฌ์ธ ๋ชจ๋‹ˆํ„ฐ(Monitor)์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณธ๋‹ค.

์„ธ๋งˆํฌ๋Š” ์‹ค์ œ๋กœ ๋งค์šฐ ์˜ค๋ž˜๋œ ๋™๊ธฐํ™” ๋„๊ตฌ์ด๋‹ค. ํ˜„์žฌ์—๋Š” ๋ชจ๋‹ˆํ„ฐ(monitor)๋ผ๋Š” ๋™๊ธฐํ™” ๋„๊ตฌ๋ฅผ ์ฃผ๋กœ ์‚ฌ์šฉํ•˜๋ฉฐ, ์ด๋Š” ์ข€ ๋” ๊ณ ์ˆ˜์ค€์˜ ๋™๊ธฐํ™” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.

1. ๋ชจ๋‹ˆํ„ฐ ๊ตฌ์กฐ

Semaphore์˜ ๊ตฌ์กฐ๋Š” ์œ„์™€ ๊ฐ™์•˜๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด monitor๋Š” ๋ฌด์—‡์ด ๋‹ค๋ฅผ๊นŒ?

์œ„๋Š” ๋ชจ๋‹ˆํ„ฐ์˜ ๊ตฌ์กฐ๋ฅผ ๊ฐ„๋‹จํžˆ ๋‚˜ํƒ€๋‚ธ ๊ทธ๋ฆผ์ด๋‹ค. ๋ชจ๋‹ˆํ„ฐ๋Š” ๊ณต์œ  ์ž์› + ๊ณต์œ  ์ž์› ์ ‘๊ทผํ•จ์ˆ˜๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ๊ณ , 2๊ฐœ์˜ ํ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค. ๊ฐ๊ฐ mutual exclusion(์ƒํ˜ธ๋ฐฐํƒ€) queue, conditional synchronization(์กฐ๊ฑด๋™๊ธฐ) queue์ด๋‹ค.

  • ์ƒํ˜ธ๋ฐฐํƒ€ ํ๋Š” ๋ง๊ทธ๋Œ€๋กœ ๊ณต์œ  ์ž์›์— ํ•˜๋‚˜์˜ ํ”„๋กœ์„ธ์Šค๋งŒ ์ง„์ž…ํ•˜๋„๋ก ํ•˜๊ธฐ ์œ„ํ•œ ํ์ด๋‹ค.
  • ์กฐ๊ฑด๋™๊ธฐ ํ๋Š” ์ด๋ฏธ ๊ณต์œ ์ž์›์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ํ”„๋กœ์„ธ์Šค๊ฐ€ ํŠน์ •ํ•œ ํ˜ธ์ถœ wait()์„ ํ†ตํ•ด ์กฐ๊ฑด๋™๊ธฐ ํ๋กœ ๋“ค์–ด๊ฐˆ ์ˆ˜ ์žˆ๋‹ค.

์กฐ๊ฑด๋™๊ธฐ ํ์— ๋“ค์–ด๊ฐ€ ์žˆ๋Š” ํ”„๋กœ์„ธ์Šค๋Š” ๊ณต์œ ์ž์›์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค์— ์˜ํ•ด ๊นจ์›Œ์ค„ ์ˆ˜ ์žˆ๋‹ค. ์ด ์—ญ์‹œ ๊นจ์›Œ์ฃผ๋Š” ํ”„๋กœ์„ธ์Šค์—์„œ ํŠน์ •ํ•œ ํ˜ธ์ถœ notify()์„ ํ•ด์ฃผ๋ฉฐ, ๊นจ์›Œ์ฃผ๋”๋ผ๋„ ์ด๋ฏธ ๊ณต์œ ์ž์›์„ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š” ํ”„๋กœ์„ธ์Šค๊ฐ€ ํ•ด๋‹น ๊ตฌ์—ญ์„ ๋‚˜๊ฐ€์•ผ ๋น„๋กœ์†Œ ํ์— ์žˆ๋˜ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์‹คํ–‰๋œ๋‹ค.

2. monitor in java

์ž๋ฐ”๋Š” ๋ชจ๋‹ˆํ„ฐ๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋Œ€ํ‘œ์ ์ธ ์–ธ์–ด์ด๋ฉฐ, ์ž๋ฐ”์˜ ๋ชจ๋“  ๊ฐœ์ฒด๋Š” ๋ชจ๋‹ˆํ„ฐ๊ฐ€ ๋  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ์ž๋ฐ”๋ฅผ ํ†ตํ•ด ๋ชจ๋‹ˆํ„ฐ์— ๋Œ€ํ•œ ์˜ˆ์ œ๋ฅผ ์‚ดํŽด๋ณด์ž.

class C {
  private int value, ...;     // ๊ณต์œ  ๋ณ€์ˆ˜
  synchronized void Foo() {   // ๋ฐฐํƒ€๋™๊ธฐ
    // ...
  }
  synchronized void Goo() {
    // ...
  }
  void H() {
    // ...
  }
}

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

Foo() ํ•จ์ˆ˜์™€ Goo() ํ•จ์ˆ˜๋Š” synchronized ํ‚ค์›Œ๋“œ๋ฅผ ํ†ตํ•ด ์ƒํ˜ธ๋ฐฐํƒ€ ํ•จ์ˆ˜๋กœ ์„ ์–ธํ•˜์˜€๋Š”๋ฐ, ์ด๋Š” **โ€œ๋‘˜ ๋‹ค ๊ฐ™์€ ์ž„๊ณ„๊ตฌ์—ญ์„ ๊ฐ–๋Š”๋‹คโ€**๋Š” ์˜๋ฏธ์ด๋‹ค. ๋‹ค์‹œ ๋งํ•ด์„œ, Foo() ํ•จ์ˆ˜์— ํ•œ ์“ฐ๋ ˆ๋“œ๊ฐ€ ์ˆ˜ํ–‰ ์ค‘์ด๋ผ๋ฉด, Foo() ํ•จ์ˆ˜๋ฟ ์•„๋‹ˆ๋ผ Goo() ํ•จ์ˆ˜์—๋„ ๋‹ค๋ฅธ ์“ฐ๋ ˆ๋“œ๋Š” ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋‹ค. ๋ฐ˜๋ฉด์— H() ํ•จ์ˆ˜๋Š” ์ผ๋ฐ˜ ํ•จ์ˆ˜์ธ๋ฐ, ์ด ํ•จ์ˆ˜์—์„œ๋Š” ๊ณตํ†ต ๋ณ€์ˆ˜์— ๋Œ€ํ•œ ์—…๋ฐ์ดํŠธ๋ฅผ ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ์„ ์˜ˆ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. (์—ฌ๋Ÿฌ ์“ฐ๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— ์ ‘๊ทผ๊ฐ€๋Šฅํ•˜๋‹ค.)

์กฐ๊ฑด๋™๊ธฐ๋Š” ํŠน์ •ํ•œ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

wait(): ํ˜ธ์ถœํ•œ ์“ฐ๋ ˆ๋“œ๋ฅผ ์กฐ๊ฑด๋™๊ธฐ ํ์— ์‚ฝ์ž…ํ•œ๋‹ค. notify(): ์กฐ๊ฑด๋™๊ธฐ ํ์— ์žˆ๋Š” ํ•˜๋‚˜์˜ ์“ฐ๋ ˆ๋“œ๋ฅผ ๊นจ์›Œ์ค€๋‹ค. notifyAll(): ์กฐ๊ฑด๋™๊ธฐ ํ์— ์žˆ๋Š” ๋ชจ๋“  ์“ฐ๋ ˆ๋“œ๋ฅผ ๊นจ์›Œ์ค€๋‹ค.

๋ชจ๋‹ˆํ„ฐ ์—ญ์‹œ, ์„ธ๋งˆํฌ์—์„œ ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์ธ Mutual exclusion, Ordering์„ ๋ชจ๋‘ ํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด ์ด๋ฅผ ์‚ดํŽด๋ณด์ž.

3. Problem Solving by Monitor

monitor๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ง€๊ธˆ๊นŒ์ง€ ๋ฐฐ์šด ๋ฌธ์ œ๋“ค์„ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด ์•Œ์•„๋ณด์ž.

3.1 BankAccount Problem

์ด์ „์— ์„ธ๋งˆํฌ์—์„œ ์‚ดํŽด๋ณธ ์€ํ–‰๊ณ„์ขŒ ๋ฌธ์ œ๋ฅผ ํ†ตํ•ด ์„ธ๋งˆํฌ ๋Œ€์‹  ๋ชจ๋‹ˆํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด์„œ Mutual exclusion, Ordering์„ ๊ตฌํ˜„ํ•ด๋ณด์ž.

3.1.1 Mutual Exclusion

class Test {
	public static void main(String[] args)
	throws InterruptedException {
		BankAccount b = new
		BankAccount();
		Parent p = new Parent(b);
		Child c = new Child(b);
		p.start();
		c.start();
		p.join();
		c.join();
		System.out.println( "\nbalance = " + b.getBalance());
	}
}
 
class BankAccount {
	int balance;
	synchronized void deposit(int amt) {
		int temp = balance + amt;
		System.out.print("+");
		balance = temp;
	}
	synchronized void withdraw(int amt) {
		int temp = balance - amt;
		System.out.print("-");
		balance = temp;
	}
	int getBalance() {
		return balance;
	}
}
 
class Parent extends Thread {
	BankAccount b;
	Parent(BankAccount b) {
		this.b = b;
	}
	public void run() {
		for (int i=0; i<100; i++)
			b.deposit(1000);
	}
}
 
class Child extends Thread {
	BankAccount b;
	Child(BankAccount b) {
		this.b = b;
	}
	public void run() {
		for (int i=0; i<100; i++)
			b.withdraw(1000);
	}
}

์ฝ”๋“œ๊ฐ€ ๋งค์šฐ ๊ฐ„๋‹จํ•ด์กŒ๋‹ค..!{:.center-text}

์œ„ ์ฝ”๋“œ์—์„œ ๋ณผ ์ˆ˜ ์žˆ๋“ฏ์ด, ์„ธ๋งˆํฌ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋ณด๋‹ค ๋ชจ๋‹ˆํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋งค์šฐ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค. ์„ธ๋งˆํฌ๋ฅผ ์„ ์–ธํ•˜๊ณ  number of permit ๊ฐ’์„ ์„ค์ •ํ•˜๋Š” ๋Œ€์‹ , synchronized ํ‚ค์›Œ๋“œ ํ•˜๋‚˜๋กœ ์ด๋ฅผ ๋Œ€์ฒดํ•œ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

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

์‹คํ–‰ ๊ฒฐ๊ณผ๋Š” ์œ„์™€ ๊ฐ™๊ณ , balance๊ฐ’์ด ์ •์ƒ์ ์œผ๋กœ 0์„ ์ถœ๋ ฅํ•œ๋‹ค.

3.1.2 Mutual Ordeing

์€ํ–‰๊ณ„์ขŒ ๋ฌธ์ œ๋ฅผ ์‚ดํŽด๋ณด๊ธฐ์ „์—, ordering์„ ํ•˜๊ธฐ ์œ„ํ•ด ๋ชจ๋‹ˆํ„ฐ๋ฅผ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•˜๋Š”์ง€ ๋ณด์ž.

|P1|P2| |::|::| ||wait()| |section 1|section 2| |notify()||

์œ„ ๊ตฌ์กฐ๋Š” ํ”„๋กœ์„ธ์Šค ์ˆœ์„œ๋ฅผ P1, P2 ์ˆœ์„œ๋กœ ์‹คํ–‰ํ•˜๊ธฐ ์›ํ•˜๋Š” ๊ฒฝ์šฐ์ด๋ฉฐ, ์ด๋Š” ์„ธ๋งˆํฌ์™€ ๋งค์šฐ ์œ ์‚ฌํ•œ ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ์€ํ–‰๊ณ„์ขŒ ๋ฌธ์ œ๋ฅผ ๋ชจ๋‹ˆํ„ฐ๋กœ ๊ตฌํ˜„ํ•˜๋Š”๋ฐ, ์ž…๊ธˆ ๋จผ์ € ์ˆ˜ํ–‰, ์ถœ๊ธˆ ๋จผ์ € ์ˆ˜ํ–‰, ์ž…๊ธˆ ์ถœ๊ธˆ ๋ฐ˜๋ณต ์ˆ˜ํ–‰ 3๊ฐ€์ง€๋ฅผ ๊ฐ๊ฐ ๊ตฌํ˜„ํ•ด๋ณด์ž. ๊ทธ๋ฆฌ๊ณ  ์œ„ ์ฝ”๋“œ์—์„œ ์ˆ˜์ •ํ•˜๋Š” ๋ถ€๋ถ„์€ ์ˆœ์„œ๋ฅผ ์ •ํ•˜๋Š” ์ž…๊ธˆ, ์ถœ๊ธˆํ•จ์ˆ˜์ด๋ฏ€๋กœ ์ด ๋ถ€๋ถ„์„ ๋Œ€๋ณ€ํ•˜๋Š” BankAccount๋งŒ ์ˆ˜์ •ํ•˜์ž.

์ž…๊ธˆ ๋จผ์ € ์ˆ˜ํ–‰ํ•˜๊ธฐ

๋จผ์ € ์ž…๊ธˆ์‹œ์ž‘ํ•˜๋ฉด ๊ธฐ๋‹ค๋ฆฌ๋ผ๊ณ  ํ•˜๋ฉด๋œ๋‹ค.

class BankAccount {
	int balance;
	synchronized void deposit(int amt) {
		int temp = balance + amt;
		System.out.print("+");
		balance = temp;
		notify();
	}
	synchronized void withdraw(int amt) {
		while (balance <= 0)
			try {
				wait();
			} catch (InterruptedException e) {}
		int temp = balance - amt;
		System.out.print("-");
		balance = temp;
	}
	int getBalance() {
		return balance;
	}
}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++------------------------------------------------------------
----------------------------------------
balance = 0

์ถœ๊ธˆ ๋จผ์ € ์ˆ˜ํ–‰ํ•˜๊ธฐ

๋จผ์ € ์ถœ๊ธˆ์‹œ์ž‘ํ•˜๋ฉด ๊ธฐ๋‹ค๋ฆฌ๋ผ๊ณ  ํ•˜๋ฉด๋œ๋‹ค.

class BankAccount {
	int balance;
	synchronized void deposit(int amt) {
		while (balance == 0)
			try {
				wait();
			} catch (InterruptedException e) {}
		int temp = balance + amt;
		System.out.print("+");
		balance = temp;
	}
	synchronized void withdraw(int amt) {
		int temp = balance - amt;
		System.out.print("-");
		balance = temp;
		notify();
	}
	int getBalance() {
		return balance;
	}
}
--------------------------------------------------------------------------------
--------------------++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++++++
balance = 0

์ž…๊ธˆ ์ถœ๊ธˆ ๋ฐ˜๋ณต ์ˆ˜ํ–‰ํ•˜๊ธฐ

์ž…๊ธˆ ๋„ฃ๊ณ  ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์ถœ๊ธˆ ๋„ฃ๊ณ  ๊ธฐ๋‹ค๋ฆฌ๊ณ ๋ฅผ ๋ฐ˜๋ณตํ•˜๋ฉด ๋œ๋‹ค!

class BankAccount {
	int balance;
	boolean p_turn = true;
	synchronized void deposit(int amt) {
		int temp = balance + amt;
		System.out.print("+");
		balance = temp;
		notify();
		p_turn = false;
		try {
			wait();
		} catch (InterruptedException e) {}
	}
	synchronized void withdraw(int amt) {
		while (p_turn)
			try {
				wait();
			} catch (InterruptedException e) {}
		int temp = balance - amt;
		System.out.print("-");
		balance = temp;
		notify();
		p_turn = true;
	}
	int getBalance() {
		return balance;
	}
}
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
balance = 0

3.2 ์ „ํ†ต์  ๋™๊ธฐํ™” ๋ฌธ์ œ

10: ์ „ํ†ต์ ์ธ ๋™๊ธฐํ™” ๋ฌธ์ œ๋“ค์„ ์ˆ˜์ •ํ•ด๋ณธ๋‹ค!

2.1 Producer-Consumer Problem

Semaphore๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ƒํ˜ธ ๋ฐฐ์ œ sem, ๊ฐ€๋“ ์ฐจ์žˆ์„ ๋•Œ blockํ•˜๋Š” sem, ๋น„์–ด์žˆ์„ ๋•Œ blockํ•˜๋Š” sem ์ด 3๊ฐœ๋ฅผ ์‚ฌ์šฉํ–ˆ์–ด์•ผ ํ–ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋ฒˆ์—๋Š” ์ฝ”๋“œ๊ฐ€ ๊ฐ„๋‹จํ•ด์ง„๋‹ค!

class Buffer {
    int[] buf;
    int size, count, in, out;
    Buffer(int size) {
        buf = new int[size];
        this.size = size;
        count = in = out = 0;
    }
 
    synchronized void insert(int item) {
        while (count == size)
            try {
                wait();
            } catch (InterruptedException e) {}
        buf[in] = item;
        in = (in+1)%size;
        notify();
        count++;
    }
 
    synchronized int remove() {
        while (count == 0)
            try {
                wait();
            } catch (InterruptedException e) {}
        int item = buf[out];
        out = (out+1)%size;
        count--;
        notify();
        return item;
    }
}
 
class Producer extends Thread {
    Buffer b;
    int N;
    Producer(Buffer b, int N) {
        this.b = b; this.N = N;
    }
    public void run() {
        for (int i=0; i<N; i++)
            b.insert(i);
    }
}
 
class Consumer extends Thread {
    Buffer b;
    int N;
    Consumer(Buffer b, int N) {
        this.b = b; this.N = N;
    }
    public void run() {
        int item;
        for (int i=0; i<N; i++)
            item = b.remove();
    }
}
 
class Test {
    public static void main(String[] arg) {
        Buffer b = new Buffer(100);
        Producer p = new Producer(b, 10000);
        Consumer c = new Consumer(b, 10000);
        p.start();
        c.start();
        try {
            p.join();
            c.join();
        } catch (InterruptedException e) {}
        System.out.println("Number of items in the buf is " + b.count);
    }
}
Number of items in the buf is 0

2.2 The Dining Philosopher Problem

class Philosopher extends Thread {
    int id; // philosopher id
	Chopstick lstick, rstick;
    Philosopher(int id, Chopstick lstick, Chopstick rstick) {
        this.id = id;
        this.lstick = lstick;
        this.rstick = rstick;
    }
 
    public void run() {
        try {
            while (true) {
                lstick.acquire();
                rstick.acquire();
                eating();
                lstick.release();
                rstick.release();
                thinking();
            }
        }catch (InterruptedException e) { }
    }
 
    void eating() {
        System.out.println("[" + id + "] eating");
    }
    void thinking() {
        System.out.println("[" + id + "] thinking");
    }
}
 
class Chopstick {
    private boolean inUse = false;
    synchronized void acquire() throws InterruptedException {
        while (inUse)
            wait();
        inUse = true;
    }
    synchronized void release() {
        inUse = false;
        notify();
    }
}
 
class Test {
    static final int num = 5; // number of philosphers & chopsticks
    public static void main(String[] args) {
        int i;
        /* chopsticks */
        Chopstick[] stick = new Chopstick[num];
        for (i=0; i<num; i++)
            stick[i] = new Chopstick();
        /* philosophers */
        Philosopher[] phil = new Philosopher[num];
        for (i=0; i<num; i++)
            phil[i] = new Philosopher(i, stick[i], stick[(i+1)%num]);
        /* let philosophers eat and think */
        for (i=0; i<num; i++)
            phil[i].start();
    }
}

์ด ์ฝ”๋“œ๋Š” ๊ต์ฐฉ์ƒํƒœ๋ฅผ ํ•ด๊ฒฐํ•˜์ง€ ์•Š์€ ์ƒํƒœ์ด๋‹ค. ํ•ด๊ฒฐ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” circular wait ์กฐ๊ฑด์„ ๋ถˆ๋งŒ์กฑํ•˜๋„๋ก ๋งŒ๋“ค๋ฉด ๋œ๋‹ค. ์ด ๋ถ€๋ถ„์—์„œ๋Š” ์‰ฝ๊ฒŒ ๋™๊ธฐํ™” ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Œ์„ ๋ณด๊ณ ๊ฐ€๋ฉด ๋œ๋‹ค.

Reference