운영체제에서 가장 중요한 건 프로세스 관리이다.
프로세스 관리
현대 컴퓨터의 메모리에는 여러 프로세스가 존재하는데,
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(); // start(): 쓰레드를 실행하는 메서드
c.start();
p.join(); // join(): 쓰레드가 끝나기를 기다리는 메서드
c.join();
System.out.println("balance = " + b.getBalance());
}
}
// 계좌
class BankAccount {
int balance;
void deposit(int amount) {
balance = balance + amount;
}
void withdraw(int amount) {
balance = balance - amount;
}
int getBalance() {
return balance;
}
}
// 입금 프로세스
class Parent extends Thread {
BankAccount b;
Parent(BankAccount b) {
this.b = b;
}
public void run() { // 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);
}
}
이를 실행하면 1000원을 100번 입금하고(입금쓰레드), 1000원을 100번 출금하기에 (출금쓰레드)
balance = 0 의 결과값을 얻을 수 있음.
하지만,2개의 쓰레드에 시간 지연을 시켜본다면?
// 계좌
class BankAccount {
int balance;
void deposit(int amount) {
int temp = balance + amount;
System.out.print("+");
balance = temp;
}
void withdraw(int amount) {
int temp = balance - amount;
System.out.print("-");
balance = temp;
}
int getBalance() {
return balance;
}
}
이를 실행하면
+++++++---------++++-----------------------------++++++++++++++++++++----------------+++++++++++++++++++++++++++++++++++++++++----------------------------------------------++++++++++++++++++++++++++++
balance = 100000 의 값이 나옴.
은행 계좌 문제에서의 공통변수 balance
balance = balance + amount; // 입금
balance = balance - amount; // 출금
void deposit(int amount) {
balance = balance + amount;
}
void withdraw(int amount) {
balance = balance - amount;
}
원하는 결과값을 도출하도록 임계구역 문제를 해결
프로세스의 실행 순서를 원하는대로 제어
Busy wait 등과 같은 비효율성을 제거
-> P: Proberen (test) → acquire()
-> V: Verhogen (increment) → 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()
release()
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로 설정해두어, 패런트가 공통변수값을 계산할 때 value=0, 끝나면 value = 1
패런트가 계산 중일 때, 차일드가 들어오려해도
임계구역의 문제를 해결하였으므로, 이를 실행하면 balance = 0 의 결과값을 얻을 수 있다.
참고
강의 : http://www.kocw.net/home/search/kemView.do?kemId=978503
정리 : https://velog.io/@codemcd/운영체제OS-8.-프로세스-동기화-1