동기화

윤혜림·2023년 6월 27일
0

스레드들은 동일한 데이터를 공유하기 때문에 매우 효율적으로 작업 할 수 있다.
하지만 동일한 메모리를 사용하기 때문에 2가지 문제 발생
1.스레드 간섭
2.메모리 불일치 문제

스레드 간섭

여러 개의 스레드가 공유된 데이터에 동시에 접근할 때 발생.
하나의 스레드가 공유 데이터 값을 변경하고 있는 중간에, 다른 스레드가 끼어들면 이상한 결과가 나온다.
ex) 공유 프린터를 한 사람이 사용하고 있는데 다른 사람이 공유 프린터 사용을 하면 출력이 섞이게 된다.

메모리 불일치

스레드에 따라서 공유된 메모리 값이 일치하지 않는 현상

이러한 오류를 막는 도구를 동기화 라고 한다.

스레드 동기화 방법

공유된 자원 중에서 동시에 사용하면 안 되는 자원을 보호하는 도구
밀폐된 방 안에 자원을 놓고 한 번에 하나의 스레드만 방문을 열고 사용할 수 있게 하는 것

공유 프린터기를 사용할 때 다른 사람이 쓰고 있으면 끝날 때 까지 기다려야한다.
이런 부분을 임계영역 이라고 한다.

스레드 간섭 예제

package ex16;

import ex16.Printer.MyThread1;

class Printer {
    void print(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i] + "");
            try {
                Thread.sleep(100);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    class MyThread1 extends Thread {
        Printer prn;
        int[] myarr = { 10, 20, 30, 40, 50 };

        MyThread1(Printer prn) {
            this.prn = prn;
        }

        public void run() {
            prn.print(myarr);
        }

    }

}

class MyThread2 extends Thread {
    Printer prn;
    int[] myarr = { 1, 2, 3, 4, 5 };

    MyThread2(Printer prn) {
        this.prn = prn;
    }

    public void run() {
        prn.print(myarr);
    }
}

public class TestSynchro {
    public static void main(String[] args) {
        Printer obj = new Printer();
        MyThread1 t1 = new MyThread1(obj);
        MyThread2 t2 = new MyThread2(obj);
        t1.start();
        t2.start();
        // 스레드들이 Print 객체를 동시에 접근하여서 배열을 출력하기 때문

    }

}

실행 결과는 실행할 때마다 달라진다.
=>스레드들이 Printer 객체를 동시에 접근해서 배열을 출력하기 때문
Printer 객체:임계영역

동기화

위의 문제를 막으려면 동기화를 사용
1. 동기화 메소드
2. 동기화 블록
3. 정적 동기화

Printer 객체 영역은 임계영역이다.
이런 경우 synchronized 키워드를 사용해서 메소드나 코드에 lock을 걸어야 한다.

동기화 메소드 예제

먼저 동기화된 메소드는 동시 호출 되더라도 마이크로 단계들이 겹치지 않는다.
하나의 스레드가 동기화된 메소드를 실행하고 있으면 그 스레드가 종료할 때 까지 모든 스레드는 중지 된다.이것은 스레드 간섭 문제를 해결한다.
동기화된 메소드가 종료되면 자동적으로 이후의 메소드 호출은 변경된 상태만을 볼 수있다 이것은
메모리 불일치 오류 문제를 해결한다.

교착(데드락) 예제

교착

스레드 간의 조정
스레드로 하여금 조건을 반복 루프에서 무한정 검사하게 하는것 = 폴링

보다 효율적인 방법은 조건이 만족될 때까지 현재의 스레드를 일시 중지시키는 것
wait()를 사용하면 다른 스레드가 어떤 이벤트가 발생했다고 알려줄때까지 스레드가 중지된다.

wait(): 어떤 일이 일어나기를 기다릴때 사용하는 메소드
notifyAll() : 반대로 어떤 일이 일어났을 때 알려주는 메소드

profile
도라에몽

0개의 댓글