수업시간에 살펴본 synchronization 도구와 관련하여, 다양한 프로그래밍 언어에서 사용하는 방법에 대해 정리 및 구체적인 예를 제시하여 설명하시오.
Java에서 synchronization tool를 사용하는 예제에 대해서 조사해보았다.
synchronization tool in java
자바의 synchronization tool 중 synchronized 키워드를 사용한 방법과 monitor 방법이 있다.
1. synchronized 키워드
synchronized 키워드 방법 중 synchronization method를 사용한 예시를 살펴본다.
//example of java synchronized method
class Table{
synchronized void printTable(int n){//synchronized method
for(int i=1;i<=5;i++){
System.out.println(n*i);
try{
Thread.sleep(400);
}catch(Exception e){System.out.println(e);}
}
}
}
class MyThread1 extends Thread{
Table t;
MyThread1(Table t){
this.t=t;
}
public void run(){
t.printTable(5);
}
}
class MyThread2 extends Thread{
Table t;
MyThread2(Table t){
this.t=t;
}
public void run(){
t.printTable(100);
}
}
public class TestSynchronization2{
public static void main(String args[]){
Table obj = new Table();//only one object
MyThread1 t1=new MyThread1(obj);
MyThread2 t2=new MyThread2(obj);
t1.start();
t2.start();
}
}
코드를 해석해보면,
Table 클래스 안에는 printTable이라는 동기화된 메서드가 있다.
"synchronized" 키워드는 한 번에 하나의 스레드만 메서드를 실행할 수 있게하여 여러 스레드가 메서드에 동시에 액세스하여 shared data를 액세스 하는 것을 방지하는데 사용된다.
printTable 메서드는 int형 매개변수 n을 받아 n구구단을 5까지 출력한다.
이 메서드에는 스레드가 잠자고 있는 동안 발생할 수 있는 예외를 처리하는400초 간격의 try-catch 블록이 포함되어있다.
MyThread1, MyThread2 라는 두 개의 개별 스레드를 생성하고 각각은 Table 인스턴스를 멤버변수로 가지고 있다.
MyThread1, MyThread2는 각각의 생성자에 Table 인스턴스를 매개변수로 전달하여 생성된다.
각 스레드의 "run" 멤버 함수는 해당 Table 인스턴스의 메서드인 printTable를 호출하여 5, 100을 전달한다.
마지막으로 main 함수에서 Table 인스턴스를 하나만 만들고 두 스레드에 전달하여 t1, t2 스레드 인스턴스를 생성한다.
그런 다음 start 를 통해 두 스레드를 실행시킨다.
Table 클래스의 printTable 이 동기화되어있어 하나의 스레드만 이 메서드를 실행하여 동시 액세스를 방지할 수 있기 때문에 t1 스레드가 전달해 준 5값으로 구구단을 출력한다음, t2 스레드가 전달해 준 100값으로 구구단을 출력하여 불일치나 충돌없이 순서대로 출력되는 결과를 확인할 수 있다.
2. Monitor
semaphore의 deadlock 문제에 대한 해결방안으로 프로그래밍 언어에서의 synchronization tool을 사용하는 방법이 있다.
monitor는 그 중 하나로 java에서만 제공하는 synchronization tool이다.
monitor의 구성
- Thread 단위로 monitor lock을 획득하거나 반환(acuire lock/ release lock)
- synchronization code를 수행할 때는 대상 instance의 monitor lock을 획득한 후 critical section안으로 진입이 가능, synchronization code를 벗어날 때는 monitor lock을 반환한다.
- synchronization instance 별로 결합된 monitor가 존재한다.
monitor의 메서드인 wait, notifyAll 방법을 사용하면 한 번에 하나의 스레드만 공유 데이터에 액세스할 수 있고 스레드가 공유 데이터를 사용할 수 없는 경우 공유 데이터에 대한 액세스를 기다릴 수 있다.
monitor의 사용 예시를 살펴본다.
public class Channel {
private String packet;
private boolean isPacketExist;
public synchronized void send(String packet) {
while (isPacketExist) {
try {
wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
Log.error("Thread interrupted", e);
}
}
isPacketExist = true;
this.packet = packet;
notifyAll();
}
public synchronized String receive() {
while (!isPacketExist) {
try {
wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
Log.error("Thread interrupted", e);
}
}
isPacketExist = false;
notifyAll();
return packet;
}
}
코드를 해석해보면,
Channel 클래스는 두 스레드 간에 데이터(패킷)을 전송하는데 "send" 및 "receive"(송신 및 수신)라는 두 개의 synchronized 메서드를 사용한다.
producer-consumer 예시에서 본다면 send는 producer에 해당되고 recieve는 consumer에 해당된다.
즉, send 메서드는 Channel에 패킷을 넣는 스레드에서 사용되고 receive 메서드는 스레드가 Channel에서의 패킷을 이용하는데 사용된다.
이 메서드들은 모니터 메서드인 wait, notiyfyAll 메서드를 사용하여 공유 데이터(전역 변수)인 packet과 플래그 역할을 하는 isPacketExist에 대한 액세스를 동기화한다.
즉, 이 두 메서드는 동기화된 방법으로 한 번에 하나의 스레드만 실행할 수 있게된다.
send 메서드는 스레드가 wait 상태인 스레드에게 패킷을 보내는데 사용된다. send메서드가 호출되면 먼저 isPacketExist 변수를 확인해하여 채널에 패킷이 있는지 확인한다. Channel에 패킷이 있으면 Producer 스레드는 isPacketExist가 false가 될 때까지(즉, Consumer 스레드가 채널에서 패킷을 반환할 때까지) Channel 클래스 내에서 wailt() 메서드를 호출하여 대기한다.
isPacketExist가 false가 되면 isPacketExist를 true로 설정하고 패킷을 channel 클래스의 패킷 변수에 저장한다.
현재 monitor 객체의 매서드인 notiyfyAll()을 호출하여 대기 중인 모든 스레드(Consumer 스레드)를 깨워 Channel에서 패킷을 사용할 수 있음을 나타낸다.
recieve 메서드가 호출되면 isPacketExist변수로 패킷이 있는지 확인하고 없으면 패킷을 사용하려는 스레드는 isPacketExist 변수가 true가 될 때까지 기다리게 된다.
Producer 스레드가 패킷을 채워 넣어 isPacketExist가 true가 되면, Cosumer 스레드는 Channel 내의 패킷 변수에서 패킷을 제거하고 isPacketExist를 false로 설정한 뒤 notifyAll()로 대기 중인 스레드(Producer 스레드)를 깨워서 새 패킷을 받을 준비가 되었다는 신호를 보내게 된다.
즉, 두 가지 메서드 방법은 동기화된 방식으로 스레드간에 데이터를 전송하기 위해 함께 작동하여 Producer, Consumer 스레드가 동시에 채널에 액세스하지 않도록 하여 공유 데이터를 보호할 수 있다.
reference)
https://www.javatpoint.com/synchronization-in-java
https://ssup2.github.io/programming/Java_Monitor_synchronized/
'운영체제' 카테고리의 다른 글
[6주차 토의 주제] <article review> CFS Linux (0) | 2023.04.08 |
---|---|
[5주차 토의 주제] Threads & Concurrency (0) | 2023.03.31 |