3-2 세마포

2023. 3. 20. 16:32운영체제

1. 세마포 : 프로세스 동기화 문제 해결을 위한 소프트웨어 도구

① P(=acquire) : 세마포 내부의 정수가 1 감소. 값이 음수이면, block상태(메소드 실행 도중에 콘텍스트 스위칭이 일어나서 다른 메소드가 실행되는 일은 없다)

② V(=release) : 세마포 내부의 정수가 1 증가. 값이 음수/0이면, ready queue로 보내어 wake up

 

☞세마포 내부 정수 값이 음수일 때, 그 절대값은 현재 세마포 내부큐에서 블록 되어있는 프로세스의 개수

☞세마포의 내부 정수 값(=number of permit)은 P 동작을 호출했는데도 블록되지 않고 계속 진행할 수 있는 프로세스 개수

 

 

 

2. 세마포를 사용한 동기화

1) 상호배타 : 임계구역에 최대 하나의 프로세스만. 즉, number of permit=1

Semaphore sem=new Semaphore(1);		//number of permit=1
sem.acquire();
//////////////
Critical-Section
//////////////
sem.release();

ex) 세마포를 사용한 상호배타 조건의 만족 (순서)

parent쓰레드와 child쓰레드

2) 실행 순서 제어

ex) P1: S1(statement);

     P2: S2;

▶ 둘 중 하나가 선택되어 프로세스가 실행될 것인데, P1이 먼저 선택되면 S1코드 먼저, P2가 먼저 선택되면 S2코드 먼저 실행된다.

 

ex) P1: S1;  sem.release();

     P2: sem.acquire();  S2;

▶ number of permit=0;으로 초기값을 두고, 둘 중 어떤 것이 선택되어도 S1이 먼저 실행된다.

import java.util.concurrent.Semaphore;

class BankAccount{			//은행계좌 클래스
 int balance;			//현재 잔액
 Semaphore sem=new Semaphore(1);		//for 상호배타
 Semaphore sem2=new Semaphore(0);		//for 진행. parent 항상 먼저
 void deposit(int amount){		//입금
	try{
	sem.acquire();
	} catch(InterruptedException e) {}
	//////////////////////////////////
	balance=balance+amount;		//parent의 임계구역
	System.out.print("+");
	//////////////////////////////////
	sem.release();
	sem2.release();
 }
 void withdraw(int amount){		//출금
	try{
	sem2.acquire();
	sem.acquire();
	} catch(InterruptedException e) {}
	//////////////////////////////////
	balance=balance-amount;		//child의 임계구역
	System.out.print("-");
	//////////////////////////////////
	sem.release();
 }
 int getBalance(){			//잔액조회
	return balance;
 }
}

class Parent extends Thread{		//부모 쓰레드
 BankAccount b;
 int count;
 Parent(BankAccount b, int count){
	this.b=b;
	this.count=count;
 }
 @Override
 public void run(){			//1원씩 count번 입금
	for(int i=0;i<count;i++)
		b.deposit(1);
 }
}

class Child extends Thread{
 BankAccount b;
 int count;
 Child(BankAccount b, int count){
	this.b=b;
	this.count=count;
 }
 @Override
 public void run(){			//1원씩 count번 출금
	for(int i=0;i<count;i++)
		b.withdraw(1);
 }
}

class Test{			//메인 프로그램
 static final int MAX=5000;		//입출금 횟수
 public static void main(String[] args) throws InterruptedException{
	BankAccount b=new BankAccount();
	Parent p=new Parent(b,MAX);
	Child c=new Child(b,MAX);

	p.start();
	c.start();
	p.join();
	c.join();
	System.out.println(b.getBalance());
 }
}

위의 코드를 실행하면 CPU의 프로세스 선택 순서에 관계없이 항상 parent thread가 먼저 돌것이다.(=입금이 먼저)

 

ex) 부모: deposit(); sem2.release(); sem3.acquire();

     자식: sem2.acquire(); withdraw(); sem3.release();

▶ 위는 입출금이 교대로 반복된다.

import java.util.concurrent.Semaphore;

class BankAccount{			//은행계좌 클래스
 int balance;			//현재 잔액
 Semaphore sem=new Semaphore(1);		
 Semaphore sem2=new Semaphore(0);	
 Semaphore sem3=new Semaphore(0);	
 void deposit(int amount){		//입금
	try{
	sem.acquire();
	//////////////////////////////////
	balance=balance+amount;		//parent의 임계구역
	System.out.print("+");
	//////////////////////////////////
	sem.release();
	sem2.release();
	sem3.acquire();
	} catch(InterruptedException e) {}
 }
 void withdraw(int amount){		//출금
	try{
	sem2.acquire();
	sem.acquire();
	} catch(InterruptedException e) {}
	//////////////////////////////////
	balance=balance-amount;		//child의 임계구역
	System.out.print("-");
	//////////////////////////////////
	sem.release();
	sem3.release();
 }
 int getBalance(){			//잔액조회
	return balance;
 }
}

class Parent extends Thread{		//부모 쓰레드
 BankAccount b;
 int count;
 Parent(BankAccount b, int count){
	this.b=b;
	this.count=count;
 }
 @Override
 public void run(){			//1원씩 count번 입금
	for(int i=0;i<count;i++)
		b.deposit(1);
 }
}

class Child extends Thread{
 BankAccount b;
 int count;
 Child(BankAccount b, int count){
	this.b=b;
	this.count=count;
 }
 @Override
 public void run(){			//1원씩 count번 출금
	for(int i=0;i<count;i++)
		b.withdraw(1);
 }
}

class Test{			//메인 프로그램
 static final int MAX=5000;		//입출금 횟수
 public static void main(String[] args) throws InterruptedException{
	BankAccount b=new BankAccount();
	Parent p=new Parent(b,MAX);
	Child c=new Child(b,MAX);

	p.start();
	c.start();
	p.join();
	c.join();
	System.out.println(b.getBalance());
 }
}

 

'운영체제' 카테고리의 다른 글

quiz4  (0) 2023.03.20
quiz5  (0) 2023.03.20
3-1 프로세스 동기화  (0) 2023.03.20
♥ 2. 프로세스  (0) 2023.03.20
2-4 추가  (0) 2023.03.20