ํ์ฌ ์ฌ์ฉํ๋ ๋๊ธฐํ ๋๊ตฌ์ธ ๋ชจ๋ํฐ(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
- KOCW ์ํฌ์ฌ ๊ต์๋ - ์ด์์ฒด์
- ์ํฌ์ฌ ๊ต์๋ ๋ธ๋ก๊ทธ(์ํ ๊ธฐ์ถ ๋ฌธ์ )
- codemcd ๋์ ์ ๋ฆฌ๊ธ
- Operating System Concepts, 9th Edition - Abraham Silberschatz