아무나개발하자

동기화(synchronization) 본문

OS

동기화(synchronization)

개발천재나천재 2023. 1. 14. 11:31

멀티 스레드 동시성 문제를 보여주기 위해 코드를 작성해 보았다.

 

Counter

class Counter{
    private int state = 0;
    
    public void increment(){
        state++;
    }
    
    public void get(){
        System.out.println("현재 상태는 : " + state + "입니다.");
    }
}

state라는 전역변수를 공유해서 사용할때의 문제를 보여주기 위해 작성을 했다. increment() 메소드는 state를 +1해주는 메소드이다.

 

MyThread1

class MyThread1 extends Thread{
    Counter counter;
    
    public MyThread1(Counter counter) {
        this.counter = counter;
    }
    
    @Override
    public void run(){
        for (int i = 0; i <1000; i++){
            counter.increment();
            counter.get();
        }
    }
}

MyThread1이 하는일은 간단하다. state에 +1을 1000번 반복하는것이다.

 

 

MyThread2

class MyThread2 extends Thread{
    Counter counter;

    public MyThread2(Counter counter) {
        this.counter = counter;
    }

    @Override
    public void run(){
        for (int i = 0; i < 1000; i++){
            counter.increment();
            counter.get();
        }
    }
}

MyThread2도 하는일은 간단하다. state에 +1을 1000번 반복하는것이다.

 

 

Program

public class Program{
    /**
     * 1. myThread1에서 1씩 더하는것을 1000번 반복
     * 2. myThread2에서 1씩 더하는것을 1000번 반복
     * 3. main에서 각각 100개식 생성해서 run
     * 4. 그러면 결과는 200000 이 항상 나와야된다.
     */
    public static void main(String[] args){
        Counter counter = new Counter();
        for(int i = 0; i < 100; i++){
            Thread myThread1 = new MyThread1(counter);
            Thread myThread2 = new MyThread2(counter);
            myThread1.start();
            myThread2.start();
        }

    }
}

Program에서는 MyThread1을 100개 MyThread2도 100개를 만들어서 RUN(state에 +1을 1000번 수행)을 수행하는 것이다. 결과는 (1000 * 2) * 100번 수행되서 결과는 200000이 나와야한다.

 

 

결과

하지만 결과를 보면 일정하지 않은 이상한 값이 나오는것을 알수 있다. 이러한 현상을 multi thread의 동시성 문제라고 한다. 이유는 밑에서 알려주겠다.

 

위에 상황을 보면 200개의 스레드를 생성했고, 각각의 스레드들은 모두 state라는 변수를 공유해서 사용한다. 그럼 공유해서 사용할때 왜 문제가 생기냐??? 그건 밑에 그림과 함께 설명하겠다.

사실은 state++라고 작성한 코드가 CPU에서 실행될때는 한줄의 코드가 아니다... 위에 보면 3줄의 코드로 실행되는데, 여기서부터 중요하다. 앞서서 설명한 CPU는 quantum단위로 스레드 컨텍스트 스위칭을 한다고 했다. 그런데 위에 3줄짜리 코드를 CPU가 수행하다 2번째줄에서 컨텍스트 스위칭이 일어났을때 문제가 발생한다.

예를 들어 Th1이 2번째 줄까지 수행하다가 컨텍스트 스위칭이 일어났다고 하자 그러면 Th2가 실행이되고 3줄의 코드를 수행하면 LOAD할때 state = 0을 로드하고 3줄의 코드를 완료했다고 하자 그러면 state는 1이된다. 그리고 다시 Th1이 2번째줄부터 수행을 하면 state는 1이된다. 두개의 스레드가 state++연산을 두번했음에도 불구하고 state는 1이되는 문제가 발생하게 되는것이다. 이러한 문제를 race condition이라고 한다.

 

 

Race Condition

여러 프로세스/스레드가 동시에 같은 데이터를 조작할때, 타이밍이나 접근 순서에 따라 결과가 달라질 수 있는 상황

 

 

동기화(synchronization)

여러 프로세스/스레드를 동시에 실행해도 공유 데이터의 일관성을 유지하는 것!

 

 

그러면 어떻게 동기화를 시킬것인가??

- increment() 메소드를 한 스레드만 실행하게 하자라는 아이디어!

 

Critical Section(임계 영역)

공유데이터의 일관성을 보장하기 위해 하나의 프로세스/스레드만 진입해서 실행 가능한 영역

critical section에 접근하기 이전에 entry section에서 critical section에 접근이 가능한지의 여부를 확인한다

 

 

critical section problem의 해결책이 되기 위한 조건 (3가지 조건을 다 만족해야된다!)

 

1. mutual exclusion (상호 배제)

-  한번에 하나의 프로세스/스레드만 critical section에서 실행할 수 있도록 한다.

2. progress (진행)

- critical section이 비워져 있고, 다른 프로세스나 스레드들이 critical section에 들어가기를 원한다면 그 중에 하나는 실행이 되도록 해야 한다. 즉 진행이 되야한다.

3. bounded waiting (한정된 대기)

- 어떤 프로세스나 스레드가 무한정 critical section에 들어가지 못하고 기다리면 안된다.

 

 

참고 : https://www.youtube.com/watch?v=vp0Gckz3z64&list=PLcXyemr8ZeoQOtSUjwaer0VMJSMfa-9G-&index=4

'OS' 카테고리의 다른 글

CPU bound, IO bound  (0) 2023.01.13
Context Switching  (0) 2023.01.12
스레드 정리  (0) 2023.01.03
운영체제 정리 1탄  (0) 2023.01.02